java集合之Map
Java Map
Set 与 Map家族
Set: hashSet, LinkedHashSet (HashSet + LinkedList),TreeSet
Map: HashMap, LinkedHashMap (hashMap + 双向链表), TreeMap
Hash函数 -> Bucket
冲突
重写hashcode + equals, Object做key时,hashcode 和equal 一致。否则,两个逻辑相同的对象,会到不同bucket。
OBject Default:
equal: 同一个reference
hashcode: 不同对象返回唯一的哈希值
链地址 + 开放地址法: 1.8 之前,bucket后加链表存储hashcode的相同, 1.8 引入红黑树
jdk1.8: 当链表长度太长(默认超过 8)时,链表就转换为红黑树。我们可以利用红黑树快速增删改查的特点,提高 HashMap 的性能。当红黑树结点个数少于 8 个的时候,又会将红黑树转化为链表。因为在数据量较小的情况下,红黑树要维护平衡,比起链表来,性能上的优势并不明显。
rehashing
- capacity
- load factor :
加载因子 = 填入表中的元素个数 / 散列表的长度
如果超过load factor(0.75),数组扩容至2倍,导致重新计算的bucket index发生变化
高并发的rehashing以及线程安全1
例如在resize的临界点,多线程执行put ; resize + rehash 会导致并发问题。
- 在jdk1.7中,在多线程环境下,扩容时会造成环形链或数据丢失。
- 在jdk1.8中,在多线程环境下,会发生数据覆盖的情况。
参考
LinkedHashMap
LinkedHashMap = HashMap + 双向链表。
可以按照插入的顺序(或者访问顺序)输出, 取决于accessOrder
(true时表示按访问顺序排序,false表示按插入顺序排序。)
accessOrder 为true, get 和 update 都会把元素挪到双向链表的尾部 (类似LRU)
TreeMap
treeMap底层是红黑树, 按照key的自然顺序(或指定顺序comparator)
- NavigableMap
- SortedMap
head, tail, floor , ceiling ...
HashMap 1.8 源代码
成员变量:
/** * 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.) */
Node<K,V>[] table
int size;
/**
The number of times this HashMap has been structurally modified
Structural modifications are those that change the number of mappings in
the HashMap or otherwise modify its internal structure (e.g.,
rehash). This field is used to make iterators on Collection-views of
the HashMap fail-fast. (See ConcurrentModificationException). */
int modCount;
threshold;
loadFactor
put
方法

resize
方法
newCap = oldCap << 1 // new cap 设置为原来两倍,通过移位操作 |
// 旧数据迁移 |
例如,扩容从16到32.
其他
HashMap 面试题 https://mp.weixin.qq.com/s/Fhks3dHxAdsQL3RrLr8xlQ
Reference
https://mp.weixin.qq.com/s/HaP1dbofRTAn-XMlhtZn-g
参考Post not found: 多线程之并发相关容器 多线程之并发相关容器 关于ConcurentHashMap↩︎