基础概念
数据结构
jdk1.7
数据 + 双向链表
头插法,并发情况下,可能产生循环链表
a.next = head,a = head<br>b.next = head,b = head<br>并发情况下<br>a.next = b,b.next = a
Entry
存储键值对的对象,内含4个属性,hashcode、next指针、key和value
数组中每个元素会存储一个Entry
发生hash冲突的时候,才会使用链表或者红黑树
为什么链表长度为8并且数组长度为64的时候转红黑树
前置知识:HashMap中的哈希表包含了数组和链表或红黑树这两种数据结构
链表长度为8
泊松分布
链表长度为7的时候发生hash碰撞的概率是千万分之6
链表长度为8的时候发生hash碰撞的概率是亿分之3
链表时间复杂度O(N),红黑树时间复杂度O(logN)
数组长度为64
可以为其树化箱的最小表容量。(否则,如果箱中的节点过多,则会调整表的大小。<br>应至少为 4 * TREEIFY_THRESHOLD(8)以避免调整大小和树化阈值之间的冲突<br>
最小是32,所以临界值是32,64避免临界值
如果数组的容量小于64,则认为是哈希表太小,导致的hash冲突,<br>这种情况下,会进行数组扩容,而不是转换红黑树
此处提供调试hashmap测试代码,通过重写hashcode提高碰撞率来供demo使用
为什么链表长度为6的时候转回链表
防止临界值导致链表和红黑树频繁的转化导致的性能损耗
HashMap VS HashSet<br>
HashSet的key重复就跳过不操作,HashMap的Key重复就更新value
HashMap VS ConcurrentHashMap<br>
<br>
ConcurrentHashMap线程安全,jdk1.7是分段锁。jdk1.8是桶级别的锁<br>
个人感觉实际业务开发的场景使用其实蛮小的,实际业务中,大部分场景是单线程同步运行的<br>即使遇到多线程的场景,可以也被包装成业务对象了