HashMap知识点总结

1、HashMap长度为什么是2的n次幂?

1)节省空间

2)减少哈希碰撞概率

2、HashMap如何解决哈希冲突?

采用链表

3、HashMap在多线程中使用会出现什么问题?如何解决

1)多个线程put可能导致元素丢失

//关键点1
if ((p = tab[i = (n - 1) & hash]) == null)
     tab[i] = newNode(hash, key, value, null);

//关键点2
if ((e = p.next) == null) {
     p.next = newNode(hash, key, value, null);
     if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
            treeifyBin(tab, hash);
     break;
}

举例:

线程A和线程B同时调用put方法,都走到关键点1处,都判断当前节点为空,线程A先执行创建新节点,之后线程B执行创建新节点会覆盖上一个已添加的元素,导致元素丢失。

关键点2同样的原理

2)put和get并发执行可能导致get为空

如果put时正好遇到需要扩容,扩容的过程中会新创建一个节点数组,然后再把数组搬运到新数组中。如果线程B此时调用get,那么获取到的元素即为空。

//关键点
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
    //赋值给全局变量
    table = newTab;

解决方案:

1)对HashMap的操作加锁

2)使用ConcurrentHashMap替代

3)使用Collections.synchronizedMap(hashMap)

4、HashMap什么时候会扩容?

1.8: put元素后超过阀值 或 链表超过8且长度小于64

5、Java1.8 HashMap为什么使用链表+红黑树?

链表的查找效率为O(n),而红黑树的查找效率为O(logn),查找效率变高了。

红黑树的查找效率虽然变高了,但是插入效率变低了,如果从一开始就用红黑树并不合适。从概率学的角度选了一个合适的临界值为8。

在源码的注释中也给出了相关原因:

Because TreeNodes are about twice the size of regular nodes, we
use them only when bins contain enough nodes to warrant use
(see TREEIFY_THRESHOLD)

因为树节点的大小是链表节点大小的两倍,所以仅在包含足够数量节点时才使用它。这个数量就是8。

6、HashMap在JDK1.7和1.8的区别?

1.7:

1)构造方法中会初始化一个EmptyTable

2)hashMap由数组+链表组成

3)对于哈希碰撞,采用头插入法

4)哈希算法不同

5)扩容时迁移数据计算节点角标方式不同hash & (length-1)

1.8:

1)无,仅对负载因子和阀值变量赋值

2)hashMap由数组+链表+红黑树组成

3)对于哈希碰撞采用尾插入法(避免了死循环)

4)哈希算法采用高16位和低16位异或(异或:不同为1,相同为0)

5)扩容时迁移数据计算节点角标hash & oldCap,为0放在原位置,为1放在i+oldTable.length

7、hashcode和equals的区别?

hashcode:将任意一个对象根据指定的算法转为32位int

equals:比较两个对象是否相等

hash值相同,对象并不一定相同,equals相同,hash值一定相同

8、HashMap是否允许存放null?

允许,key、value都可以,放在第一位

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值