Java18 Collection单列集合Set

Collection常见的方法: dce7b77e8b59bd64cb8d41f67c53affd_MD5 set都可以使用.

Set是一个interface:

Set<String> s = new HashSet<>();
add的返回值:表示原有集合中是否有某个元素.

Set的几个子类的toString方法是重写了的,可以直接打印


51afe40b4ddb077adf18c00d2ebb5cff_MD5 - HashSet 139c752eef84ae2091711d2fb2b93e07_MD5 91c8a95d3755b90545ff16fb83d7359d_MD5 tip:为什么是& ? 因为这样可以使得index肯定小于数组长度-1.源码就是这么写的 事实上,这是一种非常常见的方式。我们阅读下面可以发现,数组长度-1的二进制数一定都是11111...从而,达到了对哈希值取模的作用。 为什么不直接取模?因为直接用%的话,编译器并不知道数组长度-1这个值的特性,因此无法优化成位运算。

hashCode():Object中的方法,返回一个整数,表示对象的哈希值 ad50631fddb817b54ace9a6b8c18f183_MD5 重写的时候,一般来说,需要让属性值相同的不同对象Hash值一样.

可以右键帮我们重写: 3652e1563831429d2396feb3af98f2fc_MD5 f35fc88873aa82838730f38e86371cde_MD5 重写之后这两者hash值就是一样的.

有没有哈希碰撞的例子?有: 88b22c604e983079cd3da62f7b3a2e48_MD5 这两者就是一样的.

  • 实现原理 9e744d824ce9f353e55db9a6283f490a_MD5 数组是一个Node* 类型的数组. 默认加载因子:就是负载因子.指存储元素总个数/数组容量 然后就是正常的拉链法. 内部比较是否有重复元素的时候,用的是equals方法. 拉链插入的时候: b515c14d11ed992d1911422e1de21fea_MD5 也就是JDK8之前是头插,之后是尾插.

之后,如果负载因子大于0.75,那么数组会扩容两倍. 另外,如果链表长度大于8,数组长度大于等于64时,当前的链表就会变为红黑树.(JDK8以后) 存储自定义对象,必须重写hashCode和equals方法.否则没有什么意义.

HashSet()遍历的时候,是从数组的第一个pos开始依次往后遍历的.


  • LinkedHashSet(不常见)

是HashSet的子类.它保证存储和取出的元素顺序一致. 如何保证的: fd33e331f473dccbe045f60dbbd31251_MD5 遍历的时候,就从双向链表的头遍历到尾. 67b1e026d4e23fdab7b6c49fc6793f53_MD5


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

字符/字符串:按照字典序进行排序的


如何自定义比较规则: 29bbc89897b0445526d3ca30c18ac9bc_MD5 18c4aa66377f255aa0647b002c71479e_MD5 5ec28286407007b6c0de2956647cb08a_MD5 3e10c2993f79b277fe9261374c2271fa_MD5

第二种:(如果第二种和第一种都是同时存在的,那么第二种规则会优先覆盖掉第一种) ba657c4f253134eb416072dfb9262ea2_MD5 d3c0941b0e2bb1e107408b4c6d8519d2_MD5 23a7634fdb824255a0bde555826cd46e_MD5 当然,由于是函数式接口,可以改成Lambda表达式.

如果自定义的类对象没有实现方式12,那么add时会抛出异常.


源码: 19c24f4a1498e21af5ed9f7031b10e21_MD5 8c49392cec67ad079c8553fc93b8d90e_MD5 a2a3cb11379ae006ed8bd7946c4ada78_MD5 2e8b03b5d3817b735906a25b5d90b3ff_MD5 1bc375ab29816d2dd7684ec038705666_MD5