HashMap复习时候的一些问题总结

在获取hash值的时候,为什么要对hashcode进行一个右移16位的操作

1
2
3
4
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

答: 目的是为了将hashcode的高位和低位进行混合,从而减少hash冲突的发生,也只能降低hash冲突的可能,增加性能.

为什么hash冲突会影响性能

因为hashmap最好的性能是实现O1的查找,插入,删除效率,但是由于会出现hash冲突,会导致多个值被装进同一个桶中,在hashmap里面桶里面的数据结果是用链表,红黑树来实现的,链表和红黑树的插入删除查找的复杂度增加了,就导致了hashmap的效率降低了.
为了减少hash冲突,应该选择合适的hash函数.调整hash表的大小,调整合适的装载因子.
hashmap里面默认的装载因子是0.75.

扩容发生在哪些情况

  1. 当hashmap里面的所有键值对的数量超过了设置的hashmap容量(默认大小16),时候会发生扩容

什么情况下会转换成红黑树

当单个桶的数量超过8的时候:

1
2
3
int TREEIFY_THRESHOLD = 8;
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);

线程安全的话使用谁比较好

首先需要知道HashMap不是线程安全的.
线程安全的有:

  • HashTable
  • ConcurrentHashMap

HashTable : 实现的线程安全很简单,他直接给 put get 方法进行上锁(synchronized).这就导致在插入获取数据的时候效率会降低.
ConcurrentHashMap : 他在获取数据的时候效率比HashTable高,因为 get操作是不加锁的,他用了 volatile 关键字进行修饰,这个关键字保证了有序性和可见性,保证了每次获取的数据都是最新的.然后在 put 的时候使用乐观锁实现同步问题.