HashMap:
结构:
jdk1.7结构为 数组+链表
jdk1.8后 结构为 数组+链表+红黑树
每个节点是一个Node,实现了Entry接口 Entry<K,V>
Node :
字段:key,value,hash,next (如下) next(hash冲突时连接链表)
红黑树中节点:除了需要记录一个上面的Node,还需要下面的这些字段
点击 上面 extends的 LinkedHashMap.Entry<K,V>,显示如下
点击 上面 super(...),显示如下
1.7Hashmap会有什么问题?
1.7hashMap中链表是头插法,高并发下可能会造成死循环,所以1.8hashMap改成了尾插法
https://www.bilibili.com/video/BV1hE411A77Z?p=4
https://www.bilibili.com/video/BV184411v77T?from=search&seid=9768616371408166594
e.next = newTable[i] 是为了把e移动过去后,新数组的这个节点成为e节点的下一位,成为链表
扩容机制:
hashMap长度默认16 modCount字段记录长度
懒加载,第一次put时创建
达到百分之75(扩容因子为0.75)后扩容为原来的2倍
链表什么时候转换成红黑树?
1、链表长度达到8
且 2、HashMap数组长度达到64
否则都是做扩容。
红黑树什么时候降为链表?
红黑树长度小于等于6时,降为链表 避免频繁来回转化
为什么需要扩容呢?
因为如果填充比很大,说明利用的空间很多,如果一直不进行扩容的话,链表就会越来越长,这样查找的效率很低,因为链表的长度很大(当然最新版本使用了红黑树后会改进很多),扩容之后,将原来链表数组的每一个链表分成奇偶两个子链表分别挂在新链表数组的散列位置,这样就减少了每个链表的长度,增加查找效率
为什么引入红黑树?:
因为链表查询慢,得找到一个节点,然后通过next找下一个节点,红黑树类似于二分法查找,效率高一些
为什么不直接用红黑树?
节点少,效率差不太多,但红黑树占用空间更大
链表转红黑树为什么选用8?
通过泊松分布算出,当桶中结点个数为8时,出现的几率是亿分之6的,因此常见的情况是桶中个数小于8的情况,此时链表的查询性能和红黑树相差不多,因为转化为树还需要时间和空间,所以此时没有转化成树的必要。
hashMap扩容为什么是2倍?(还需详细了解)
https://blog.csdn.net/gududedabai/article/details/85784161
1、减少碰撞
2、采用的是位运算,因为位运算效率高于取模运算
如果数组长度不是2的指数次幂,那位运算的时候可能会下标越界
ConcurrentHashMap:线程安全,
jdk1.7:是分段锁,把map分成一段一段的锁
jdk1.8:直接用Node(数组+链表+红黑树)的数据结构来实现,
不是锁整个方法,Synchronized、CAS 来操作
有不完善的或者理解不正确的还望海涵!以后还会完善