为什么不管大厂还是小厂,面试总是要提到 HashMap?(上)

简介: 不知道大家最近有没有刷过 Java 面试题,有没有发现几乎所有面试题或多或少都会包括 HashMap 面试题。为什么 Java 中小小的一个 HashMap,值得在面试中被反复提到?阿粉认为是因为 HashMap 太重要了,大家回看一下自己的业务代码,是不是都有在使用 HashMap ?即使你真的没有直接使用,但是你使用的一些中间件,或者一些开源框架,这些代码肯定使用 HashMap 完成相关逻辑。而 HashMap 包含很多核心知识点,从这些知识点可以考察出一个面试者基本知识掌握情况。

Hello,大家好,我是阿粉~

不知道大家最近有没有刷过 Java 面试题,有没有发现几乎所有面试题或多或少都会包括 HashMap 面试题。

为什么 Java 中小小的一个 HashMap,值得在面试中被反复提到?

阿粉认为是因为 HashMap 太重要了,大家回看一下自己的业务代码,是不是都有在使用 HashMap ?

即使你真的没有直接使用,但是你使用的一些中间件,或者一些开源框架,这些代码肯定使用 HashMap 完成相关逻辑。

而 HashMap 包含很多核心知识点,从这些知识点可以考察出一个面试者基本知识掌握情况。

其实就算没有面试,我们也应该或多乎或少去了解 一下 HashMap 基本实现原理。因为如果使用 HashMap 不当,很容易写出一连串 Bug,而且可能还不容易排查。

HashMap 面试题网上很多,但是其实怎么问他都离不开这些核心知识点。

这就像我们以前解答数学题一样,背后答案都是围绕核心数学公式。

所以我们只要掌握 HashMap 核心知识点,就不用再怕面试中再问到。

这里阿粉整理一下,HashMap 涉及核心知识点如下:

  • 底层数据结构
  • Hash 算法
  • 寻址算法
  • 扩容
  • 多线程并发

底层数据结构

数据结构与算法是最近面试越来越注重考查的一方面,尤其是对于校招来讲,这一块百分百会涉及。

而 HashMap 底层结构一下子就涉及三大数据结构,数组、链表、红黑树。

数组

HashMap 中元素实际保存在一个个 Node 中,而Node 类保存在底层数组中。

35.jpg

以上代码来自 JDK1.8,JDK1.7 为 Entry 类型。

实际上 Node 为 Entry 类的子类

链表

我们观察一下Node 类的数据结构,

36.jpg

可以发现 Node 类中有一个 next 字段,用于保存下一个 Node 元素,通过这种方式就形成一个单向的链表。

那为什么需要链表那?

这可能与下面说道 Hash算法有关,因为再好的 Hash 算法,都有可能导致不同输入产生相同的输出。

37.jpg

来自:阮一峰的博客

如果不同的输入得到了同一个哈希值,就发生了"哈希碰撞"(collision)。

哈希碰撞解决办法很多,这里 HashMap 就采用拉链法,即使用一个链表保存碰撞的元素的。

其他办法还有:

  • 线行探查法
  • 平方探查法
  • 双散列函数探查法

红黑树

由于链表查找元素复杂度为 O(N),如果 HashMap 哈希碰撞很厉害,从而导致大部分元素落在同一个链表上,这就会导致 HashMap 性能会下降,极端一点 HashMap O(1) 查询复杂度退化成 O(N)的复杂度。

JDK1.8 中引入红黑树数据结构,当链表元素等于 8 时,链表转化为红黑树,这样查找复杂度就可以为 O(logn)。

38.jpg

图片来自网络

那为什么使用红黑树,而不是使用其他二叉树,?

这是因为红黑树对于新增与删除的操作也都能保持O(logn) 新增,这样就完美兼顾了查找与新增性能。

面试题

看完这个知识点,其实可以提很多相关数据结构面试题,比如数组与链表区别。

所以看完这个,我们就需要去整理学习数据结构相关知识。

Hash 算法

这里我们仅仅介绍一下 JDK1.8 Hash 算法。

39.jpg

它使用 key 的 hashcode 高低 16 位异或的方式计算产生。

通过这种方式,在后面寻址算法计算时候,降低碰撞的可能性。

相关文章
|
2月前
|
存储 算法 Java
【Java集合类面试八】、 介绍一下HashMap底层的实现原理
HashMap基于hash算法,通过put和get方法存储和获取对象,自动调整容量,并在碰撞时用链表或红黑树组织元素以优化性能。
|
2月前
|
Java 索引
【Java集合类面试九】、介绍一下HashMap的扩容机制
HashMap的扩容机制包括初始容量16,以2的次方进行扩充,使用负载因子0.75判断是否扩容,以及链表长度达到阈值时转换为红黑树,以优化性能。
【Java集合类面试九】、介绍一下HashMap的扩容机制
|
2月前
|
存储 Java
【Java集合类面试七】、 JDK7和JDK8中的HashMap有什么区别?
JDK7中的HashMap使用数组加链表解决冲突,而JDK8增加了红黑树结构以优化链表过长时的性能,提高查找效率。
|
2月前
|
安全 Java
【Java集合类面试十五】、说一说HashMap和HashTable的区别
HashMap和Hashtable的主要区别在于Hashtable是线程安全的,不允许null键和值,而HashMap是非线程安全的,允许null键和值。
|
2月前
|
安全 Java
【Java集合类面试十三】、HashMap如何实现线程安全?
实现HashMap线程安全的方法包括使用Hashtable类、ConcurrentHashMap,或通过Collections工具类将HashMap包装成线程安全的Map。
|
2月前
|
Java
【Java集合类面试十一】、HashMap为什么用红黑树而不用B树?
HashMap选择使用红黑树而非B树,是因为红黑树在内存中实现简单,节点更小,占用内存少,且在插入、删除和查找操作上提供更好的平衡性能。
|
2月前
|
安全 Java
【Java集合类面试十六】、HashMap与ConcurrentHashMap有什么区别?
HashMap是非线程安全的,而ConcurrentHashMap通过减少锁粒度来提高并发性能,检索操作无需锁,从而提供更好的线程安全性和性能。
|
2月前
|
Java
【Java集合类面试十四】、HashMap是如何解决哈希冲突的?
HashMap解决哈希冲突的方法是通过链表和红黑树:当链表长度超过一定阈值时,转换为红黑树以提高性能;当链表长度缩小到另一个阈值时,再转换回链表。
|
2月前
|
Java
【Java集合类面试十二】、HashMap为什么线程不安全?
HashMap在并发环境下执行put操作可能导致循环链表的形成,进而引起死循环,因而它是线程不安全的。
|
2月前
|
存储 Java
【Java集合类面试十】、HashMap中的循环链表是如何产生的?
在多线程环境下,HashMap在扩容时如果发生条件竞争,元素的插入顺序可能形成循环链表,导致死循环。
下一篇
无影云桌面