- 底层使用哈希表(数组 + 链表),当链表过长会将链表转成 红黑树以实现O(logn) 时间复杂度内查找
1. 如果链表长度超过阀值(TREEIFY_THRESHOLD == 8),就把链表转成红黑树。
1. 如果桶满了(容量 * 加载因子),就需要 resize。
1. HashMap 中 hash 函数怎么是是实现的? 还有哪些hash 的实现方式?
1. 高 16bit 不变,低 16bit 和高 16bit 做了一个异或
1. 还有哪些 Hash 实现方式:可以参考之前的博客 [Effective Java学习笔记-- hashCode()](../reading-notes/Effective-Java.md)
1. HashMap 怎样解决冲突,讲一下扩容过程,假如一个值在原数组中,现在移动了新数组,位置肯定改变了,那是什么定位到在这个值新数组中的位置,
- 这个值只可能在两个地方,一个是原下标的位置,另一种是在下标为 <原下标+原容量> 的位置。
1. 针对 HashMap 中某个 Entry 链太长,查找的时间复杂度可能达到 O(n),怎么优化?
1. 数组可以包含基本类型和对象类型,ArrayList 只能包含对象类型
1. ArrayList 提供了更多的特性(`addAll`、`removeAll`)。
- `Collections.sort(List<T> list)`;
- `sort(List<T> list, Comparator<?super T> c)`;
1. 默认容量: 16(2^n 为宜,若定义的初始容量不是 2^n,容量会定义为大于该初始容量的最小2^n)
1. 索引计算 : ((key.hashCode() ^(key.hashCode() >>> 16)) & (table.length - 1))
1. 在链表中查找,并记录链表长度,若链表长度达到了TREEIFY_THRESHOLD(8),则将该链转成红黑树。
1. 当总元素个数超过容量*加载因子时,扩容为原来 2 倍并重新散列
1. 索引计算 : (key.hashCode() &0x7FFFFFFF)%table.length
1. 当总元素个数超过容量*加载因子时,扩容为原来 2 倍并重新散列。
1. 对修改 Hashtable 内部共享数据的方法添加了 synchronized,保证线程安全。
1. HashMap、ConcurrentHashMap 区别。
1. 默认容量: 16(若定义了初始容量(c),容量会定义为大于(c + (c >>>1) +1) 的最小2^n)
- 并发性能好的原因是 ConcurrentHashMap 并不是定义synchronized 方法,而是在链表头上同步,不同的链表之间是互不影响的。