面试官问到HashMap看你会不会

1.HashMap的底层数据结构?

HashMap是我们非常常用的数据结构,由数组和链表组合构成的数据结构(也可以使用数组加树的方式实现)。
大概如下,数组里面每个地方都存了Key-Value这样的实例,在Java7叫Entry在Java8中叫Node。
在这里插入图片描述
因为他本身所有的位置都为null,在put插入的时候会根据key的hash去计算一个index值。

就比如我put(”小马“,212),我插入了为”小马“的元素,这个时候我们会通过哈希函数计算出插入的位置,计算出来index是2那结果如下。
在这里插入图片描述
HashMap中为啥需要链表,链表又是怎么样子的呢?
数组长度是有限的,在有限的长度里面我们使用哈希,哈希本身就存在概率性,就是”小马“和”小刘“我们都去hash有一定的概率会一样,就像上面的情况我再次哈希”小刘“极端情况也会hash到一个值上,那就形成了链表。(也就是说,存入的数据量是很大的,但是数组的长度是有限的,根据hash后产生的可以放的容器的总数就是数组的总数,这样,灭个数组为了能够放多个数据node,就形成了链表)
在这里插入图片描述

每一个节点都会保存自身的hash、key、value、以及下个节点,我看看Node的源码。

public class Node{
     int hash;
    String key;
    Object value;
    Node next;

}

在这里插入图片描述

2.java7和java8的区别

HashMap的Entry节点在插入链表的时候,插入的方法在java7和java8中有很大的却别:java7使用头插法,java8使用尾插法。

两种插入方法的区别:尾插法在HashMap扩容的时候可以防止形成环形链表,而头插法不能。

java8之前是头插法,就是说新来的值会取代原有的值,原有的值就顺推到链表中去,就像上面的例子一样,因为写这个代码的作者认为后来的值被查找的可能性更大一点,提升查找的效率。

HashMap的扩容机制:
数组容量是有限的,数据多次插入的,到达一定的数量就会进行扩容,也就是resize。

什么时候resize呢?
有两个因素:

  • Capacity:HashMap当前长度。
  • LoadFactor:负载因子,默认值0.75f。
    在这里插入图片描述
    怎么理解呢,就比如当前的容量大小为100,当你存进第76个的时候,判断发现需要进行resize了,那就进行扩容,但是HashMap的扩容也不是简单的扩大点容量这么简单的。

它是怎么扩容的呢?
分为两步

  • 扩容:创建一个新的Entry空数组,长度是原数组的2倍。
  • ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。

为什么要重新Hash呢,直接复制过去不行吗?
不行!!!!

是因为长度扩大以后,Hash的规则也随之改变。
Hash的公式—> index = HashCode(Key) & (Length - 1)
原来长度(Length)是8你位运算出来的值是2 ,新的长度是16你位运算出来的值明显不一样了。

扩容前:
在这里插入图片描述
扩容后
在这里插入图片描述

3.为什么java8之前用头插法,java8之后改成尾插了呢?

首先头插法的使用在hashmap扩容的时候需要重新hash,这时可能形成环形链表。

java8之后链表有红黑树的部分,大家可以看到代码已经多了很多if else的逻辑判断了,红黑树的引入巧妙的将原本O(n)的时间复杂度降低到了O(logn)。

4.HashMap的默认初始化长度是多少?

这个很简单,但很重要!!!16

那为什么是16呢?
这样是为了位运算的方便,位与运算比算数计算的效率高了很多,之所以选择16,是为了服务将Key映射到index的算法。

我前面说了所有的key我们都会拿到他的hash,但是我们怎么尽可能的得到一个均匀分布的hash呢?是的我们通过Key的HashCode值去做位运算。

使用16是为了实现hash结果在hash表中的均匀分布

5.hashCode()和equals()方法的重要性体现在什么地方?

Java中的HashMap使用hashCode()和equals()方法来确定键值对的 索引,当根据键获取值的时候也会用到这两个方法.。如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。所以这两个方法的实现对HashMap的精确性和正确性是至关重要的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良缘白马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值