Java集合面试题
HashMap
1、new HashMap(25) 是什么
实例化了一个长度为32容量的HashMap, 因为是2的次方, 容量不是25。
2、为什么 hashMap 使用 红黑书
AVL树比红黑树保持更加严格的平衡。AVL树中从根到最深叶的路径最多为~1.44 lg(n + 2),而在红黑树中最多为~2 lg(n + 1)。
是许多二叉查找树中的一种,它能保证在最坏的情况下,基本动态集合操作时间为O(lgn).
插入和删除节点导致失衡后的rebalance操作,红黑树能够提供一个比较"便宜"的解决方案,降低开销,是对search,insert ,以及delete效率的折衷,总体来说,RB-Tree的统计性能高于AVL.
https://www.cnblogs.com/wq-9/articles/14202773.html
3、什么是哈希碰撞 和 解决方式
概念:
计算得到的Hash值相同,需要放到同一个bucket中
解决方式:
Hashmap里面的bucket出现了单链表的形式,散列表要解决的一个问题就是散列值的冲突问题,通常是两种方法:链表法和开放地址法。
链表法 就是将相同hash值的对象组织成一个链表放在hash值对应的槽位;
插入一个 Entry 对象(即Key - Value), 通过Key的hashCode 与 数组长度减一,获取到其 数组坐标
分情况
1、获取到的位置,没有 Entry 对;
即该桶为null, 则直接新放入的对象, 指向 null(1.8 尾插法)
2、获取到的位置,有 Entry 对象 或者 Entry 链;
新插入的 Entry, 先通过 key 的hash 与 链表中的 key equal,
如果都不同则,插入尾部;
如果有相同的,则替换了 key 相同的 Entry 对象
开放地址法 是通过一个探测算法,当某个槽位已经被占据的情况下继续查找下一个可以使用的槽位。
为什么要用开放地址法呢,因为如果数据全都在同一个桶里面, 查询从数组变为查询链表,查询速率就会从O(1) 变为 O(n) 。
开放定址法区分为线性探查法、二次探查法、双重散列法等
参考: https://www.jianshu.com/p/379680144004
Java 8 的 哈希碰撞优化
当桶里面的长度大于 8 时, 链表变为红黑树,查询速度从 O(n)变为 O(logn)
小于 6 重新变为 链表;
4、为什么在JDK1.8中进行对HashMap优化的时候,把链表转化为红黑树的阈值是8,而不是7或者不是20呢(面试蘑菇街问过)
1)如果选择6和8(如果链表小于等于6树还原转为链表,大于等于8转为树),中间有个差值7可以有效防止链表和树频繁转换。
假设一下,如果设计成链表个数超过8则链表转换成树结构,链表个数小于8则树结构转换成链表,如果一个HashMap不停的插入、删除元素,链表个数在8左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低。
2)由于treenodes的大小大约是常规节点的两倍,因此我们仅在容器包含足够的节点以保证使用时才使用它们,
当它们变得太小(由于移除或调整大小)时,它们会被转换回普通的node节点,容器中节点分布在hash桶中的频率遵循泊松分布,桶的长度超过8的概率非常非常小。
5、为什么 HashMap 中 String、Integer 这样的包装类适合作为 key 键、
6、HashMap 中的 key若 Object类型, 则需实现哪些方法?
7、jdk7 先扩容再put jdk8 先put再扩容
8、为什么链表在get时不需要加锁,而红黑树需要加锁:
在更新期间链表遍历总是可以进行的,但是树遍历不行,因为树旋转时可能会改变根结点或者其链接。
而且,链表中成员都是value
和next
都是volatile
修饰的,所以当对链表中的元素有修改时,对其他线程是可见的。