面试官:谈谈你对HashMap的理解

53 阅读2分钟

HashMap

面试官:HashMap扩容规则是什么?

临界值=负载因子*容量.(此时的临界值为12,默认的负载因子为0.75,hashmap的容量为16)

当到达设定的临界值时,就会产生扩容,当前的容量*2

面试官:处理hash冲突的几种方式:

1.开放定址法:(细分为三种)

    1.线性探测法

    2.线性补偿探测法

    3.伪随机探测再散列

2.再哈希法:

    重新计算hash值

    缺点:增加了计算时间

3.建立公共溢出区:

    新建一张表存冲突的元素

4.链地址法(拉链法):

将近义词记录在一张表中,把冲突的位置构成链表.

优点:

     处理简单,无堆积,查找长度较短,它的空间结点还是动态申请,适合造表前无法确定表长的情况,在散列中,删除结点实现简单.

缺点:

     指针需要额外的空间.

面试官:负载因子为什么使用0.75?

假设:负载因子为 1 的情况下,提高了空间利用率,冲突的机会就越大.

假设:负载因子为 0.5 的情况下,可以减少查询时间的成本,空间利用率会降低.

最后、常见问题

HashMap中的“死锁”是怎么回事HashMap是非线程安全,死锁一般都是产生于并发情况下。

我们假设有二个进程T1、T2,HashMap容量为2,T1线程放入KeyA、B、C、D、E。

在T1线程中A、B、C Hash值相同,于是形成一个链接,假设为A->C->B,而D、E Hash值不同,于是容量不足,需要新建一个更大尺寸的hash表。

然后把数据从老的Hash表中 迁移到新的Hash表中(refresh)。这时T2进程闯进来了,T1暂时挂起,T2进程也准备放入新的key,这时也 发现容量不足,也refresh一把。

refresh之后原来的链表结构假设为C->A,之后T1进程继续执行,链接结构 为A->C,这时就形成A.next=B,B.next=A的环形链表。一旦取值进入这个环形链表就会陷入死循环,