HashMap注意点:
1.HashMap默认初试容量为16,扩容因子为0.75(到达75%的时候进行扩容),容量始终为2的幂次方。
2.HashMap实际为一个数组,因为数组是链表,所以称为散列链表。
/**
* The table, initialized on first use, and resized as
* necessary. When allocated, length is always a power of two.
* (We also tolerate length zero in some operations to allow
* bootstrapping mechanics that are currently not needed.)
*/
transient Node<K,V>[] table;
实际上是这么个玩意。
3.转红黑树的两种情况:
(1) 桶节点(单个Entry链表)的长度超过8(2) 数组长度大于等于64的时候
4.为什么hashMap的容量扩容时一定是2的幂次:
说明:key的hash值和(数组长度-1)进行 &运算。总结:因为2的幂-1都是11111结尾的,所以
(1)二进制操作效率会非常快。
(2)hash碰撞几率小。
(3)当数组长度为15(1111)时,hashcode的值会与14(1110)进行“与”运算,则最后一位永远为0,则0001,0011,0101,1001,1011,0111,1101不能存放元素,造成很大程度的空间浪费。
5. 红黑树和散列链表的优劣势
1.散列链表中的数组:查询快,修改慢2.红黑树查找和删除的时间复杂度都是O(logn),散列链表查找和删除的时间复杂度都是O(1)
(当散列链表存储的足够多的情况下,查询和扩容的效率会让人非常头疼,固在(3)情况下会转为红黑树)
3.红黑树是有序的,Hash是无序的
4.红黑树占用的内存更小(仅需要为其存在的节点分配内存),而Hash事先应该分配足够的内存存储散列表,即使有些槽可能弃用
6. 1.8之前HashMap为什么会死循环
[HashMap 在高并发下引起的死循环](https://www.jianshu.com/p/619a8efcf589)CoucurrentHashMap注意点:
1.与HashTable(整表锁)不同的是,CoucurrentHashMap在操作时是锁单个Entry链表,大大提高效率
在并发情况下,采用CAS算法对单个列表进行修改,效率还是不错的
2.(重点/核心)在并发的情况中,A线程在进行扩容,B线程在对某一Entry链表操作时,会进行如下代码流程:
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
如果当前map在进行扩容,那么B线程就会为扩容进行服务,帮助A线程进行扩容(进行数据转移)
这是一个非常复杂的操作,其中考虑到了非常多的并发情况,可以大大提高CoucurrentHashMap在并发情况下进行操作时的性能!