JavaSE——类集(下)(Set、Comparable、Collections、Comparator、Map)

第2节 集合(下)

一、Set接口

java.util.Set 接口和 java.util.List接口一样,同样继承自 Collection接口,它与Collection接口中的方法基本一致,并没有对 Collection接口进行功能上的扩充,只是比Collection接口更加严格了。

List接口不同的是, Set接口中元素无序 ,并且都会以某种规则保证存入的元素不出现重复

Set接口有很多子类:

在这里插入图片描述

比较常用的有HashSetLinkedHashSetTreeSet三个,后面分别介绍。

二、HashSet类

2.1 概述与使用

java.util.HashSetSet接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。 java.util.HashSet底层的实现其实是一个java.util.HashMap 支持,即将数据存在HashMap的键的位置,值的位置全部存放空对象。

HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于: hashCodeequals方法。hashCode就是一个生成哈希值(int型)的函数。

先来看一个使用HashSet存储的例子:

public class HashSetDemo {public static void main(String[] args) {//创建 Set集合HashSet<String> set = new HashSet<String>();//添加元素set.add(new String("123"));set.add("123");set.add("123");set.add("321");//遍历for (String name : set) {System.out.println(name);}}
} 结果如下:
123
321
说明Set集合中不能存储重复元素

2.2 构造方法与方法

在这里插入图片描述

   其中涉及到散列因子,后续介绍,**这里注意最后一种构造方法,可以将其他类型的Collection实现转为HashSet类,其他的一些类也有类似的操作** 。

在这里插入图片描述

方法也不多,增加删除遍历获取元素数比较常用。

2.3 哈希表

因为HashSet是由HashMap实现的,而HashMap又是由哈希表这种数据结构实现的,所以有必要介绍一下java中哈希表是什么。

在JDK1.8之前,哈希表底层采用数组+链表 实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树 实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间

在这里插入图片描述

当红黑树中数据个数减少到6时,从红黑树变回为链表 。这里要注意,如果本身就是链表,那么降到6也不会发生这种转变。

它存入数据时的完整过程如下图所示:

在这里插入图片描述

总而言之,JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCodeequals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCodeequals方法建立属于当前对象的比较方式。

2.4 LinkedHashSet类

此实现使客户免于HashSet提供的未指定的,通常是混乱的排序,而不会产生与TreeSet相关的增加的成本。无论原始集合的实现如何,它都可用于生成与原始集合具有相同顺序的集合的副本

三、TreeSet类与Comparable接口

3.1 TreeSet类概述

它与HashSet相比,最大的区别在于TreeSet是有序存储的。先来看一下它的构造方法和方法:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

看一个例子:

package com.kaikeba.coreclasslibrary.set;import java.util.TreeSet;public class treeset {//TreeSet:public static void main(String[] args) {TreeSet<String> data = new TreeSet<>();data.add("B");data.add("C");data.add("A");data.add("D");for(String s:data) {System.out.println(s);}}
}结果如下:
A
B
C
D

它有一个问题,当存入的数据是自定义的对象时, TreeSet通过什么来比较大小,或者再一般一些,传入上述字符串对象时,TreeSet是通过说明比较顺序的?

它本身是不知道的,所以必须实现Comparable接口。

3.2 Comparable接口

此接口对实现它的每个类的对象强加一个总排序。 这种排序被称为类的自然顺序 ,类的compareTo方法被称为其自然比较方法

它只有一个抽象方法:compareTo,它将传入的对象与此对象进行比较以获得顺序。返回负整数,零,正整数,表示此对象小于,等于或大于指定对象。

看一个例子:

package com.kaikeba.coreclasslibrary.set;import java.util.Objects;
import java.util.TreeSet;public class treeset2 {//TreeSet:public static void main(String[] args) {TreeSet<Person> data = new TreeSet<>();Person p1 = new Person("张三", 20);Person p2 = new Person("李四", 19);Person p3 = new Person("麻子", 19);data.add(p1);data.add(p2);data.add(p3);       //不能存一样大的值for(Person p:data) {System.out.println(p);}}static class Person implements Comparable<Person>{private String name;private int age;@Overridepublic int compareTo(Person o) {//this 与 o 比较//返回的数据是:负数this小、零一样大、整数this大if(this.age > o.age) {return 1;}else if(this.age == o.age) {return 0;}return -1;}public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age && Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}}
}

结果如下:

Person{name='李四', age=19}
Person{name='张三', age=20}

Person类实现了Comparable接口,实现了compareTo方法,这里对年龄进行了排序,而且也可以发现,当两者一样大时,不会存入数据。

那是不是String也做了同样的事才可以使得它能排序呢?看一下String源码:

在这里插入图片描述

在这里插入图片描述

它也是做了相同的事,才可以比较大小进行排序的。

四、Collections类和Comparator接口

4.1 Collections类

是一个集合工具类,用来对集合进行操作,部分方法如下:

  1. public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。

  2. public static void shuffle(List<?> list): 打乱集合顺序。

  3. public static <T> void sort(List<T> list) :将集合中元素按照默认规则排序。

  4. public static <T> void sort(List<T> list,Comparator<? super T> ) :将集合中元素按照指定规则排序。

举个例子:

public class CollectionsDemo {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<Integer>();//原来写法//list.add(12);//list.add(14);//list.add(15);//list.add(1000);//采用工具类 完成 往集合中添加元素Collections.addAll(list, 5, 222, 12);System.out.println(list);//排序方法Collections.sort(list);System.out.println(list);}
} 
结果:
[5, 222, 1, 2]
[1, 2, 5, 222]

这里的排序是采用的默认顺序,如果想要自定义顺序怎么操作?

4.2 Comparator接口

排序的规则是怎么定义出来的呢?说到排序,简单说就是两个对象之间比较大小,那么在Java中提供了两种比较实现的方式:

  1. 一种是比较死板的采用java.lang.Comparable接口去实现;

  2. 一种是灵活的当我需要做排序的时候再去选择java.util.Comparator接口完成。

Comparable接口中的实现,把比较规则写死了,比如想要字符串按照字符降序排序,那么就要修改String的源代码,这是不可能的,所以这个时候可以使用Comparator接口灵活的完成。

Comparator接口中主要需要重写的方法是compare方法:

public int compare(String o1, String o2):    //比较其两个参数的顺序。

两个对象比较的结果有三种:大于,等于,小于。

如果要按照升序排序,

则o1 小于o2,返回(负数),相等返回0,01大于02返回(正数)

如果要按照降序排序

则o1 小于o2,返回(正数),相等返回0,01大于02返回(负数)

操作如下:

public class CollectionsDemo3 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();list.add("cba");list.add("aba");list.add("sba");list.add("nba");//排序方法 按照第一个单词的降序Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o2.charAt(0) - o1.charAt(0);}});System.out.println(list);}
}结果如下:
[sba, nba, cba, aba]

4.3 Comparable和Comparator接口的区别

Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

Comparator:强行对某个对象进行整体排序。可以将Comparator传递给sort方法(如Collections.sortArrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序map)的顺序,或者为那些没有自然顺序的对象collection提供排序。

练习:

创建一个学生类,存储到ArrayList集合中完成指定排序操作。

Student 初始类:

public class Student{private String name;private int age;public Student() {} public Student(String name, int age) {this.name = name;this.age = age;} public String getName() {return name;} public void setName(String name) {this.name = name;} public int getAge() {return age;} public void setAge(int age) {this.age = age;} @Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

测试类:

public class Demo {public static void main(String[] args) {// 创建四个学生对象 存储到集合中ArrayList<Student> list = new ArrayList<Student>();list.add(new Student("rose",18));list.add(new Student("jack",16));list.add(new Student("abc",16));list.add(new Student("ace",17));list.add(new Student("mark",16));/*让学生 按照年龄排序 升序*/// Collections.sort(list);//要求 该list中元素类型 必须实现比较器Comparable接口for (Student student : list) {System.out.println(student);}}
}

发现,当我们调用Collections.sort()方法的时候 程序报错了。

原因:如果想要集合中的元素完成排序,那么必须要实现比较器Comparable接口。

于是我们就完成了Student类的一个实现,如下:

public class Student implements Comparable<Student>{....@Overridepublic int compareTo(Student o) {return this.age-o.age;//升序}
}

再次测试,代码就OK 了效果如下:

Student{name='jack', age=16}
Student{name='abc', age=16}
Student{name='mark', age=16}
Student{name='ace', age=17}
Student{name='rose', age=18}

补充:

如果想要规则更多一些,可以参考下面代码:

Collections.sort(list, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {// 年龄降序int result = o2.getAge()-o1.getAge()//第一个规则判断完了 下一个规则 姓名的首字母 升序if(result==0){result = o1.getName().charAt(0)-o2.getName().charAt(0);} return result;}
});

效果如下:

Student{name='rose', age=18}
Student{name='ace', age=17}
Student{name='abc', age=16}
Student{name='jack', age=16}
Student{name='mark', age=16}

五、Map接口

5.1 概述

以上的Collection中,每次操作的都是一个单独对象,而Map接口,可以实现键值对的存储 ,如下所示:

  • 张三 123456

  • 李四 234567

Map中不能包含重复的键,即键必须唯一,而且每个键最多可以映射一个值 。

Map接口与Collection接口没有任何的关系,是第二大集合操作接口。

注意:如果将可变对象用作键,则必须非常小心,因为一旦中途更改对象的属性,根据hashCodeequals方法的定义,将无法找到原来存在以该对象为键的值,即发生了哈希值错乱,后面再结合源码和例子详细解释。

5.2 方法介绍

介绍一下常用法方法:

1、删除所有映射

在这里插入图片描述

2、是否包含指定的键、值

在这里插入图片描述

3、返回Map.EntrySet视图

在这里插入图片描述

4、equals

在这里插入图片描述

5、根据键获取值

在这里插入图片描述

6、返回哈希码值

在这里插入图片描述

7、判断是否不包含映射关系

在这里插入图片描述

8、将键作为Set集合返回,遍历常用

在这里插入图片描述

9、返回包含若干个映射的不可修改Map,静态方法

在这里插入图片描述

10、存入指定的键值对

在这里插入图片描述

11、删除某映射对

在这里插入图片描述

12、替换某映射对

在这里插入图片描述

13、返回此Map中的键值对数量

在这里插入图片描述

14、返回此Map中所有值的Collection集合

在这里插入图片描述

Map本身是一个接口,所以一般会使用以下的几个子类:HashMapTreeMapHashtable

六、HashMap、Hashtable、ConcurrentHashMap类

6.1 HashMap类

6.1.1 概述

基于哈希表的Map接口的实现。 此实现提供了所有可选的映射操作,并允许null值和null键。 ( HashMap类大致相当于Hashtable ,除了它是不同步的并且允许空值。)此类不保证顺序。

此类定义如下:

public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable

它继承了AbstractMap类,同时可以被克隆,可以被序列化。

看一个例子:

package com.kaikeba.coreclasslibrary.set;import java.util.Collection;
import java.util.HashMap;
import java.util.Set;public class map {//Map//HashMap/Hashtable/ConcurrentHashMap//TreeMap//LinkedHashMappublic static void main(String[] args) {HashMap<String, String> data = new HashMap<>();data.put("key1", "锄禾日当午");data.put("key2", "汗滴禾下土");data.put("key2", "勇敢牛牛");   //新的内容将替换旧的内容//根据键来遍历键值对Set<String> set = data.keySet();for(String key:set) {System.out.println(key+"->"+data.get(key));}//遍历值Collection<String> values = data.values();for(String value:values) {System.out.println(value);}}
}结果如下所示:
key1->锄禾日当午
key2->勇敢牛牛
锄禾日当午
勇敢牛牛

6.1.2 可变对象作为键

前面也提到了,可变对象作为键会出现哈希值错乱的问题,先来看一个例子:

package com.kaikeba.coreclasslibrary.set;import java.util.HashMap;
import java.util.Objects;public class Demo {public static void main(String[] args) {//为防止键改变导致哈希值错乱的问题,尽量不要使用对象来作为键,如果要做,不要修改对象的属性HashMap<Book, String> data = new HashMap<>();Book book1 = new Book("三体", "科幻小说");data.put(book1, "第一本书");Book book2 = new Book("平凡的世界", "纪实小说");data.put(book2, "第二本书");book1.setName("四体");//哈希值通过对象属性计算,哈希值计算的与原来不一样,是找不到值的System.out.println(data.get(book1));//哈希值虽然计算一样,但是equals不相等,传入的“三体”与键对象的“四体不相等,也找不到”Book book3 = new Book("三体", "科幻小说");System.out.println(data.get(book3));}static class Book {private String name;private String info;public Book() {}public Book(String name, String info) {this.name = name;this.info = info;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Book book = (Book) o;return Objects.equals(name, book.name) && Objects.equals(info, book.info);}@Overridepublic int hashCode() {return Objects.hash(name, info);}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", info='" + info + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}}
}结果如下:
null
null

因为中途将作为键的可变对象的属性改变,导致后续找不到该键对应的值了,上述涉及到了两种情况:

  1. 直接通过改变后的对象去get,发现找不到;

  2. 新new一个与原来对象的属性完全一样的新对象去get,也找不到。

为了解释上述的现象,需要看get方法的源码:

public V get(Object key) {Node<K,V> e;return (e = getNode(hash(key), key)) == null ? null : e.value;
}

调用getNode方法,根据哈希值key来获取值,首先来看一下哈希值是如何来的:

static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

其实就是根据键来获取哈希值,若键为null,哈希值为0,若不为空,调用hashCode方法生成,而hashCode在创建类的时候已经生成:

@Override
public int hashCode() {return Objects.hash(name, info);
}

就是根据键的属性计算的一个int值,到这里就解释了第一个问题,因为存入的时候是new Book("三体", "科幻小说");,而修改了属性后键变为new Book("四体", "科幻小说");两者属性不一样,根据哈希值计算方法来看,计算得到的哈希值是不一样的,而getNode中哈希值就是寻找位置的关键,哈希值不一样肯定找不到。

最后再看一下getNode方法内部:

在这里插入图片描述

注意这里:

在这里插入图片描述

还有这里:

在这里插入图片描述

以及若在红黑树中getTreeNode方法里也有一样的判断条件,要想返回值,必须先满足这个,这里的意思就是除了哈希值要一样,键也要保持一样,但是修改之后的键是"四体", "科幻小说",而book3是"三体", "科幻小说",它们哈希值虽然一样了,但是key不一样了,这就是问题2的原因。

综上,为防止键改变导致哈希值错乱的问题,尽量不要使用可变对象来作为键,如果对象必须可变,那就不要拿它作为键使用

6.2 Hashtable类

Hashtable是一个最早的键值对操作类,本身是在JDK1.0的时候推出的,其基本操作与HashMap是类似的。

import java.util.Hashtable;
import java.util.Map;
public class HashtableDemo01 {public static void main(String[] args) {Map<String, Integer> numbers = new Hashtable<String, Integer>();numbers.put("one", 1);numbers.put("two", 2);numbers.put("three", 3);Integer n = numbers.get("two");if (n != null) {System.out.println("two = " + n);}}
}

操作的时候, 可以发现与 HashMap基本上没有什么区别, 而且本身都是以 Map为操作标准的, 所以操作的结果形式都一样。 但是 Hashtable中是不能向集合中插入 null值的。

6.3 HashMap与Hashtable的区别

在整个集合中除了ArrayListVector的区别之外,另外一个最重要的区别就是HashMapHashtable的区别:

在这里插入图片描述

6.4 ConcurrentHashMap类

HashMap是异步处理,线程不安全,但是性能较高;Hashtable是同步处理,线程安全,但是性能较低;而ConcurrentHashMap是对这两类的一个优化,采用了分段锁机制,在保证线程安全的同时,效率也比较高。

分段锁机制 就是每个哈希桶内部需要同步保证线程安全,但是桶与桶之间是异步的,提高性能。

6.5 哈希表的散列操作

注意一下这三类的构造方法,以HashMap为例:

在这里插入图片描述

涉及到两个参数:初始容量加载因子 。无参的默认初始容量为16,所有的默认加载因子为0.75。

  • 初始容量 :哈希表中哈希桶的数量;

  • 加载因子 :哈希表中有多少百分比的哈希桶中有数据,就需要进行扩容,一般是扩容为2倍,0.75就是75%。0.75是在时间和空间成本之间进行的良好的折中。较高的值会减少空间开销,但是会增加查找的成本。

为了尽量减少重新哈希(扩容)的操作,事先选择好初始容量和加载因子是很关键的(加载因子一般就选0.75)。

七、TreeMap类

TreeMap子类是允许 key 进行排序的操作子类, 其本身在操作的时候将按照 key 进行排序, 另外, key 中的内容可以为任意的对象, 但是要求对象所在的类必须实现 Comparable接口。这一点和TreeSet是类似的,毕竟,TreeSet就是TreeMap实现的。

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo01 {public static void main(String[] args) {Map<String, String> map = new TreeMap<String, String>();map.put("ZS", "张三");map.put("LS", "李四");map.put("WW", "王五");map.put("ZL", "赵六");map.put("SQ", "孙七");Set<String> set = map.keySet(); // 得到全部的keyIterator<String> iter = set.iterator();while (iter.hasNext()) {String i = iter.next(); // 得到keySystem.out.println(i + " --:> " + map.get(i));}}
}结果如下:
LS --:> 李四
SQ --:> 孙七
WW --:> 王五
ZL --:> 赵六
ZS --:> 张三

此时的结果已经排序成功了, 但是从一般的开发角度来看, 在使用 Map 接口的时候并不关心其是否排序, 所以此类只需要知道其特点即可。

八、关于Map集合的输出

8.1 使用Map.Entry接口

Collection接口中,可以使用 iterator()方法为Iterator接口实例化,并进行输出操作,但是在 Map接口中并没有此方法的定义, 所以 Map接口本身是不能直接使用 Iterator进行输出的。

因为 Map接口中存放的每一个内容都是一对值, 而使用 Iterator 接口输出的时候, 每次取出的都实际上是一个完整的对象。 如果此时非要使用Iterator进行输出的话, 则可以按照如下的步骤进行:

  1. 使用Map接口中的entrySet()方法将 Map接口的全部内容变为 Set 集合;

  2. 可以使用Set 接口中定义的iterator()方法为 Iterator接口进行实例化;

  3. 之后使用 Iterator接口进行迭代输出,每一次的迭代都可以取得一个Map.Entry的实例;

  4. 通过Map.Entry进行 keyvalue的分离。

那么, 到底什么是 Map.Entry 呢?

Map.Entry 本身是一个接口。此接口是定义在 Map接口内部的,是 Map的内部接口。此内部接口使用 static进行定义,所以此接口将成为外部接口。

实际上来讲,对于每一个存放到 Map集合中的 keyvalue都是将其变为了Map.Entry 并且将Map.Entry 保存在了Map集合之中。

在这里插入图片描述

Map.Entry接口有如下的方法:

在这里插入图片描述

Map.Entry接口中以下的方法最为常用:

在这里插入图片描述

看一个例子:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapOutDemo01 {public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("ZS", "张三");map.put("LS", "李四");map.put("WW", "王五");map.put("ZL", "赵六");map.put("SQ", "孙七");// 变为Set实例Set<Map.Entry<String, String>> set = map.entrySet();Iterator<Map.Entry<String, String>> iter = set.iterator();while (iter.hasNext()) {Map.Entry<String, String> me = iter.next();System.out.println(me.getKey() + " --> " + me.getValue());}}
}结果如下:
WW --> 王五
ZL --> 赵六
LS --> 李四
ZS --> 张三
SQ --> 孙七

以上的代码一定要记住,Map集合中每一个元素都是 Map.Entry 的实例, 只有通过Map.Entry才能进行 keyvalue的分离操作。

8.2 foreach遍历

在 JDK 1.5 之后也可以使用 foreach 完成同样的输出, 只是这样的操作基本上不使用。

import java.util.HashMap;
import java.util.Map;
public class MapOutDemo02 {public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("ZS", "张三");map.put("LS", "李四");map.put("WW", "王五");map.put("ZL", "赵六");map.put("SQ", "孙七");for (Map.Entry<String, String> me : map.entrySet()) {System.out.println(me.getKey() + " --> " + me.getValue());}}
}结果如下:
WW --> 王五
ZL --> 赵六
LS --> 李四
ZS --> 张三
SQ --> 孙七

九、类集总结

  1. 类集就是一个动态的对象数组,可以向集合中加入任意多的内容;

  2. List接口中是允许有重复元素的,Set接口中是不允许有重复元素;

  3. 所有的重复元素依靠hashCode()equals进行区分;

  4. List接口常用子类:ArrayListVector

  5. Set接口常用子类:HashSetTreeSet

  6. TreeSet是可以排序的,一个类的对象依靠Comparable接口排序;

  7. Map接口中允许存放一对内容,key→value;

  8. Map接口的常用子类:HashMapHashtableTreeMap

  9. Map使用Iterator输出的详细步骤(Map.Entry

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491519.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美国国家科学院发布《材料研究前沿:十年调查》

来源&#xff1a;中国科学院科技战略咨询研究院2月8日&#xff0c;美国国家科学院发布了针对材料研究的第三次十年调查《材料研究前沿&#xff1a;十年调查》报告。这次的调查主要评估了过去十年中材料研究领域的进展和成就&#xff0c;确定了2020-2030年材料研究的机遇、挑战和…

JavaSE——IO(上)(File、字节流、字符流、转换流、打印流、缓存流)

第3节 IO&#xff08;上&#xff09; 一、File类与文件基本操作 在程序中经常需要用到文件的操作&#xff0c;Java有专门的类来进行文件的操作——File类。 1.1 File类概述 它是对文件和目录路径名的抽象表示。 即它本身不是一个文件&#xff0c;只是一个抽象表示&#xff…

学习新技能时,大脑在如何发生改变?

来源&#xff1a;中国生物技术网众所周知&#xff0c;无论是一项运动、一种乐器还是一门手艺&#xff0c;掌握一项新技能都是需要花费时间并进行训练的。虽然我们都知道健康的大脑能够应付的来&#xff0c;但是为了开发出新行为大脑如何发生改变科学家们对此仍知之甚少。近日&a…

JavaSE——IO(下)(Properties类、序列化与反序列化)

第3节 IO&#xff08;下&#xff09; 一、.properties文件与Properties类 1.1 .properties文件介绍 .properties文件一种属性文件&#xff0c;以键值对 的格式存储内容&#xff0c;在Java中可以使用Properties类来读取这个文件&#xff0c;一般来说它作为一些参数的存储&…

VS调试dll详细过程记录

VS调试dll详细过程记录 qianghaohao(孤狼) 前言&#xff1a;在我们写的程序中有时候调用dll&#xff0c;并且需要跟踪dll中的函数&#xff0c;此时直接调试调用dll的工程是无法跳进dll的函数的&#xff0c;此时我们可以启动dll工程 来跟踪程序的走向。注意&#xff1a;要有…

谁在真正领跑 5G:技术创新和标准

来源&#xff1a;云头条5G是包括美国总统特朗普在内的所有人都在谈论的新技术。所以&#xff0c;每家公司自然都想谈论5G以及如何领跑这个领域。然而现实情况是&#xff0c;移动5G是一项涵盖甚广的无线标准&#xff0c;它改变了我们对蜂窝通信的认识&#xff0c;并前所未有地拓…

JavaSE——XML与JSON(语法格式、解析内容)

第6节 XML与JSON 一、XML 1.1 XML简介 XML全称为可扩展标记语言&#xff08;extensible Markup Language&#xff09; 。 特性&#xff1a; xml具有平台无关性&#xff0c;是一门独立的标记语言&#xff1b; xml具有自我描述性。 用途&#xff1a; 网络数据传输 数据存…

三大阶段,四大领域,详解你不知道的AIoT!

AIoT即AIIoT&#xff0c;指的是人工智能技术与物联网在实际应用中的落地融合。目前&#xff0c;越来越多的行业及应用将AI与IoT结合到了一起&#xff0c;AIoT已经成为各大传统行业智能化升级的最佳通道&#xff0c;也是未来物联网发展的重要方向。来源&#xff1a;物联网智库AI…

人类为什么会同情机器人,是否需要禁止虐待机器人

6月14日&#xff0c;一段形似波士顿动力机器人Atlas反击人类的视频在网络热传&#xff0c;制作这款视频的团队Corridor Digital&#xff0c;是一家位于洛杉矶的美国制作工作室。自2010年以来&#xff0c;一直以制作与流行文化相关的病毒在线短片视频而闻名。Corridor Digital由…

dubbo学习总结——思维导图

Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里巴巴公司开源的、轻量级的开源Java RPC框架&#xff0c;可以和Spring框架无缝集成&#xff0c;2018年阿里巴巴把这个框架捐献给了apache基金会 什么是RPC&#xff1f; RPC全称为remote procedure call&#xff0c;即远程…

python为字体添加上下标

添加上标&#xff1a;^ 添加下标&#xff1a;_ 举例&#xff1a; import numpy as np import matplotlib.pyplot as pltt np.linspace(0, 10, 1000) y np.sin(t) plt.plot(t, y) plt.xlabel(a/${m_2}$,fontdict{weight: normal, size: 15}) plt.show() 效果&#xff1a; …

微信演进的六点思考:微信生态如何演变?如何在其中掘金?

*头图来源&#xff1a;东方IC来源&#xff1a;虎嗅APP虎嗅注&#xff1a;在微信上下游诞生了无数的生态企业&#xff0c;他们关注着微信的一举一动&#xff0c;以便在其中掘金。6月15日&#xff0c;微盟集团CEO孙涛勇在华映资本WE来大会上&#xff0c;分享了对微信生态商业进化…

Day Two(Beta)

站立式会议 站立式会议内容总结 331 今天&#xff1a;指导队友学会xml布局及简单动画,解决了关于中文链接过滤器不能将iso编码改为utf8的情况(修改servletContainer默认编码) 遇到的问题&#xff1a;无 明天&#xff1a;闹钟简单实现,完善方法待解决442 今天&#xff1a;书籍评…

新技术“红”不过十年,半监督学习为什么是个例外?

来源 | 转载自知乎这一波深度学习的发展&#xff0c;以2006年Hinton发表Deep Belief Networks的论文为起点&#xff0c;到今年已经超过了10年。从过往学术界和产业界对新技术的追捧周期&#xff0c;超过10年的是极少数。从深度学习所属的机器学习领域来看&#xff0c;到底什么样…

word空格显示小点

那是因为不小心点了显示隐藏标记&#xff0c;取消即可

《细胞》重磅连发:记忆可“遗传”!

来源&#xff1a;偷鸡捕虾摸螺蛳有人说&#xff0c;记忆到最后也许是最宝贵的财富。人们总是希望能够把最珍视、最有价值的记忆保留下来。科学家们也正为此孜孜不倦的努力着。在2016年的SXSW大会上&#xff0c;南加州大学教授Theodore Berger宣布了一个轰动整个科技界的消息&am…

单词搭配用法查询网站

http://www.just-the-word.com/ 例如查询improve单词的搭配

胡小明:城市大脑与人脑不同的数据意识

一、数据应用要区别对待1.2 数据应用比数据收集重要大数据热正在席卷全国&#xff0c;许多地方政府都成立大数据局&#xff0c;统管政府的数据资源并将数据收集摆在第一位&#xff0c;数据应用研究却迟迟跟不上&#xff0c;投资不断增长应用效益却无相应增长&#xff0c;大数据…

输入关键词查询论文例句网站

http://www.scijuyi.com/es/index.php 国人开发的网站&#xff0c;专门针对英语科技论文写作。输入关键词后&#xff0c;以英文例句的形式返回检索结果。它的使用办法和谷歌学术很相似&#xff0c;但是对语料进行了挑选&#xff08;以英语为母语的语料为主&#xff09;&#x…

Redis概述以及安装

二、Redis概述以及安装 Redis是一个开源的key-value存储系统&#xff1b;和Memcached类似&#xff0c;它支持存储的value类型相对更多&#xff0c;包括string&#xff08;字符串&#xff09;、list&#xff08;链表&#xff09;、set&#xff08;集合&#xff09;、zset&#…