https://www.cnblogs.com/yysbolg/p/9230184.html
为什么 hashset 不安全, 因为内部实现用到了 hashmap
hashmap 的 put 方法不安全, resize 方法不安全, 同是 resize()方法时, 如果调用 get, 可能会产生环形的链表
为什么一定要是 2 的位数??
为了能让 HashMap 存取高效, 尽量较少碰撞, 也就是要尽量把数据分配均匀. 我们上面也讲到了过了, Hash 值的范围值 - 2147483648 到 2147483647, 前后加起来大概 40 亿的映射空间, 只要哈希函数映射得比较均匀松散, 一般应用是很难出现碰撞的. 但问题是一个 40 亿长度的数组, 内存是放不下的. 所以这个散列值是不能直接拿来用的. 用之前还要先做对数组的长度取模运算, 得到的余数才能用来要存放的位置也就是对应的数组下标. 这个数组下标的计算方法是 "(n - 1) & hash".(n 代表数组长度). 这也就解释了 HashMap 的长度为什么是 2 的幂次方.
这个算法应该如何设计呢?
我们首先可能会想到采用 % 取余的操作来实现. 但是, 重点来了:"取余 (%) 操作中如果除数是 2 的幂次则等价于与其除数减一的与 (&) 操作 (也就是说 hash%length==hash&(length-1) 的前提是 length 是 2 的 n 次方;)." 并且 采用二进制位操作 &, 相对于 % 能够提高运算效率, 这就解释了 HashMap 的长度为什么是 2 的幂次方
集合类 -- 最详细的面试宝典 -- 看这篇就够用了(java 1.8)
来源: http://www.bubuko.com/infodetail-2971498.html