内容随时更新,最大程度的分析每个方法
Set
2、HashSet
1、是一个无序的集合,且不允许存放相同的数据,且可以存放null值
2、低层调用的是HashMap的put方法
3、低层的数据结构是:数组+链表+红黑树
基本用法:
@Test
public void hashSetTest() {
//创建一个HashSet集合
HashSet<Integer> integers = new HashSet<Integer>();
Random random = new Random();
//储存数据
for (int i = 0; i < 10; i++) {
int i1 = random.nextInt(20);
//输出生成的随机数
System.out.print(i1+" ");//13 0 18 8 0 3 9 6 9 17
//添加数据到HashSet集合里面
integers.add(i1);
}
System.out.println();
//生成迭代器取出数据
Iterator<Integer> iterator = integers.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next()+" ");//0 17 18 3 6 8 9 13
}
}
构造方法:
有四种构造器能给我所用,所以有四种创建一个HashSet容器的方法
方法源码:
add源码
public boolean add(E e) {
return map.put(e, PRESENT)==null;//这个map是HashMap类型
}
//这是HashMap的put的方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//调用hashCode()生成一个哈希值,主要的作用是用来判断储存的key是否已经储存了,如果哈希值不相等,说明key值还没有储存,如果哈希相等也不能说明key是相同的,这里还要跟哈希值相等的key进行==(比较引用值)来验证key是否是相同的
}
跟进putVal源码 :逐个分析putVal里面的语句
跟进resize()方法,查看调用resize()初始化操作:
回到putVal方法中:
链表转换树形数据结构操作:treeifyBin(tab, hash);
跟进查看源码
调用treeify: 源码跟进
里面调用了三个方法:comparableClassFor、compareComparables、tieBreakOrder,跟进源码:
总结:comparableClassFor方法,该方法表示的是,存放的key的类型一定要实现Comparable接口,且里面指定的泛型的类型一定要和key的类型相同,如果相同的话,直接返回key的class类型,如果不相同的,则直接返回null.
回到treeify: 源码中