Java18 Collection单列集合Set
Collection常见的方法:
set都可以使用.
Set是一个interface:
Set<String> s = new HashSet<>();
Set的几个子类的toString方法是重写了的,可以直接打印
- HashSet
tip:为什么是& ?
因为这样可以使得index肯定小于数组长度-1.源码就是这么写的
事实上,这是一种非常常见的方式。我们阅读下面可以发现,数组长度-1的二进制数一定都是11111...从而,达到了对哈希值取模的作用。
为什么不直接取模?因为直接用%的话,编译器并不知道数组长度-1这个值的特性,因此无法优化成位运算。
hashCode():Object中的方法,返回一个整数,表示对象的哈希值
重写的时候,一般来说,需要让属性值相同的不同对象Hash值一样.
可以右键帮我们重写:
重写之后这两者hash值就是一样的.
有没有哈希碰撞的例子?有:
这两者就是一样的.
- 实现原理
数组是一个Node* 类型的数组.
默认加载因子:就是负载因子.指存储元素总个数/数组容量
然后就是正常的拉链法.
内部比较是否有重复元素的时候,用的是equals方法.
拉链插入的时候:
也就是JDK8之前是头插,之后是尾插.
之后,如果负载因子大于0.75,那么数组会扩容两倍. 另外,如果链表长度大于8,数组长度大于等于64时,当前的链表就会变为红黑树.(JDK8以后) 存储自定义对象,必须重写hashCode和equals方法.否则没有什么意义.
HashSet()遍历的时候,是从数组的第一个pos开始依次往后遍历的.
- LinkedHashSet(不常见)
是HashSet的子类.它保证存储和取出的元素顺序一致.
如何保证的:
遍历的时候,就从双向链表的头遍历到尾.

TreeSet红黑树
按照元素的默认顺序(从小到大)排序
打印/遍历都是有序:

字符/字符串:按照字典序进行排序的
如何自定义比较规则:

第二种:(如果第二种和第一种都是同时存在的,那么第二种规则会优先覆盖掉第一种)
当然,由于是函数式接口,可以改成Lambda表达式.
如果自定义的类对象没有实现方式12,那么add时会抛出异常.
源码:
