首页 > 其他分享 >HashMap常见面试题

HashMap常见面试题

时间:2023-08-16 16:59:05浏览次数:39  
标签:面试题 hash HashMap JDK 常见 链表 线程 数组

HashMap的底层数据结构?
JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用。

HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的 长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。

所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞。
JDK1.8之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值8时,将链表转化为红黑树,以减少搜索时间。

HashMap的存取原理?
1)存方法:put(Object key, Object value)

执行流程如下:

对 key 进行 hash 操作,计算存储 index; 判断是否有哈希碰撞,如果没碰撞直接放到哈希桶里,如果有碰撞则以链表的形式存储; 判断已有元素的类型,决定是追加树还是追加链表,当链表大于等于 8 时,把链表转换成红黑树; 如果节点已经存在就替换旧值; 判断是否超过阀值,如果超过就要扩容。
2)取方法:get(Object key)

执行流程如下:

首先比对首节点,如果首节点的 hash 值和 key 的 hash 值相同,并且首节点的键对象和 key 相同(地址相同或 equals 相等),则返回该节点; 如果首节点比对不相同、那么看看是否存在下一个节点,如果存在的话,可以继续比对,如果不存在就意味着 key 没有匹配的键值对。
Java7和Java8中HashMap的区别
HashMap 在 JDK 7 和 JDK 8 的主要区别如下。

存储结构:JDK 7 使用的是数组 + 链表;JDK 8 使用的是数组 + 链表 + 红黑树。 存放数据的规则:JDK 7 无冲突时,存放数组;冲突时,存放链表;JDK 8 在没有冲突的情况下直接存放数组,有冲突时,当链表长度小于 8 时,存放在单链表结构中,当链表长度大于 8 时,树化并存放至红黑树的数据结构中。 插入数据方式:JDK 7 使用的是头插法(先将原位置的数据移到后 1 位,再插入数据到该位置);JDK 8 使用的是尾插法(直接插入到链表尾部/红黑树)。
为什么HashMap线程不安全
多线程put的时候导致数据不一致 可能会因为扩容引起死循环
HashMap 在并发场景中可能出现死循环的问题,这是因为 HashMap 在扩容的时候会对链表进行一次倒序处理,假设两个线程同时执行扩容操作,第一个线程正在执行 B→A 的时候,第二个线程又执行了 A→B ,这个时候就会出现 B→A→B 的问题,造成死循环。

有什么线程安全的类代替吗
Hashtable或ConcurrentHashMap

默认初始化大小是多少?为啥是这么多?为啥大小都是2的幂?
默认初始大小是16 这样是为了位运算的方便,位与运算比算数计算的效率高了很多,之所以选择16,是为了服务将Key映射到index的算法。 为了存取高效,减少碰撞,把数据分配均匀
HashMap的扩容方式?负载因子是多少?为什么是这么多?
当hashmap中的元素个数超过负载因子×当前大小时,就会进行数组扩容,负载因子的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过12的时候,就把数组的大小扩展为32,即扩大一倍,然后重新计算每个元素在数组中的位置。

HashMap的主要参数都有哪些?
HashMap 有两个重要的参数:容量(Capacity)和负载因子(LoadFactor)。

容量(Capacity):是指 HashMap 中桶的数量,默认的初始值为 16。 负载因子(LoadFactor):也被称为装载因子,LoadFactor 是用来判定 HashMap 是否扩容的依据,默认值为 0.75f,装载因子的计算公式 = HashMap 存放的 KV 总和(size)/ Capacity。
HashMap是怎么处理hash碰撞的?
Tips:当输入两个不同值,根据同一散列函数计算出相同的散列值的现象,我们就把它叫做碰撞(哈希碰撞)
HashMap 使用链表和红黑树来解决哈希冲突

HashMap 和 Hashtable 有什么区别?
HashMap 和 Hashtable 区别如下:

Hashtable 使用了 synchronized 关键字来保障线程安全,而 HashMap 是非线程安全的; HashMap 允许 K/V 都为 null,而 Hashtable K/V 都不允许 null; 初始容量大小和每次扩充容量大小的不同。创建时如果不指定容量初始值,Hashtable 默认的初始大小为 11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来 的2倍。 JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。
为什么重写 equals() 时一定要重写 hashCode()?
因为 Java 规定,如果两个对象 equals 比较相等(结果为 true),那么调用 hashCode 也必须相等。如果重写了 equals() 但没有重写 hashCode(),就会与规定相违背。

HashMap 和HashSet区别
ConcurrentHashMap线程安全的具体实现方式/底层具体实现
首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。 ConcurrentHashMap 是由 Segment 数组结构和 HashEntry 数组结构组成。

Segment 实现了 ReentrantLock,所以 Segment 是一种可重入锁,扮演锁的角色。HashEntry 用于存储键值对数 据。

HashMap的底层数据结构? JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用。 HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的 长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。 所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞。 JDK1.8之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值8时,将链表转化为红黑树,以减少搜索时间。 HashMap的存取原理? 1)存方法:put(Object key, Object value) 执行流程如下: 对 key 进行 hash 操作,计算存储 index; 判断是否有哈希碰撞,如果没碰撞直接放到哈希桶里,如果有碰撞则以链表的形式存储; 判断已有元素的类型,决定是追加树还是追加链表,当链表大于等于 8 时,把链表转换成红黑树; 如果节点已经存在就替换旧值; 判断是否超过阀值,如果超过就要扩容。 2)取方法:get(Object key) 执行流程如下: 首先比对首节点,如果首节点的 hash 值和 key 的 hash 值相同,并且首节点的键对象和 key 相同(地址相同或 equals 相等),则返回该节点; 如果首节点比对不相同、那么看看是否存在下一个节点,如果存在的话,可以继续比对,如果不存在就意味着 key 没有匹配的键值对。 Java7和Java8中HashMap的区别 HashMap 在 JDK 7 和 JDK 8 的主要区别如下。 存储结构:JDK 7 使用的是数组 + 链表;JDK 8 使用的是数组 + 链表 + 红黑树。 存放数据的规则:JDK 7 无冲突时,存放数组;冲突时,存放链表;JDK 8 在没有冲突的情况下直接存放数组,有冲突时,当链表长度小于 8 时,存放在单链表结构中,当链表长度大于 8 时,树化并存放至红黑树的数据结构中。 插入数据方式:JDK 7 使用的是头插法(先将原位置的数据移到后 1 位,再插入数据到该位置);JDK 8 使用的是尾插法(直接插入到链表尾部/红黑树)。 为什么HashMap线程不安全 多线程put的时候导致数据不一致 可能会因为扩容引起死循环 HashMap 在并发场景中可能出现死循环的问题,这是因为 HashMap 在扩容的时候会对链表进行一次倒序处理,假设两个线程同时执行扩容操作,第一个线程正在执行 B→A 的时候,第二个线程又执行了 A→B ,这个时候就会出现 B→A→B 的问题,造成死循环。 有什么线程安全的类代替吗 Hashtable或ConcurrentHashMap 默认初始化大小是多少?为啥是这么多?为啥大小都是2的幂? 默认初始大小是16 这样是为了位运算的方便,位与运算比算数计算的效率高了很多,之所以选择16,是为了服务将Key映射到index的算法。 为了存取高效,减少碰撞,把数据分配均匀 HashMap的扩容方式?负载因子是多少?为什么是这么多? 当hashmap中的元素个数超过负载因子×当前大小时,就会进行数组扩容,负载因子的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过12的时候,就把数组的大小扩展为32,即扩大一倍,然后重新计算每个元素在数组中的位置。 HashMap的主要参数都有哪些? HashMap 有两个重要的参数:容量(Capacity)和负载因子(LoadFactor)。 容量(Capacity):是指 HashMap 中桶的数量,默认的初始值为 16。 负载因子(LoadFactor):也被称为装载因子,LoadFactor 是用来判定 HashMap 是否扩容的依据,默认值为 0.75f,装载因子的计算公式 = HashMap 存放的 KV 总和(size)/ Capacity。 HashMap是怎么处理hash碰撞的? Tips:当输入两个不同值,根据同一散列函数计算出相同的散列值的现象,我们就把它叫做碰撞(哈希碰撞) HashMap 使用链表和红黑树来解决哈希冲突 HashMap 和 Hashtable 有什么区别? HashMap 和 Hashtable 区别如下: Hashtable 使用了 synchronized 关键字来保障线程安全,而 HashMap 是非线程安全的; HashMap 允许 K/V 都为 null,而 Hashtable K/V 都不允许 null; 初始容量大小和每次扩充容量大小的不同。创建时如果不指定容量初始值,Hashtable 默认的初始大小为 11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来 的2倍。 JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。 为什么重写 equals() 时一定要重写 hashCode()? 因为 Java 规定,如果两个对象 equals 比较相等(结果为 true),那么调用 hashCode 也必须相等。如果重写了 equals() 但没有重写 hashCode(),就会与规定相违背。 HashMap 和HashSet区别 ConcurrentHashMap线程安全的具体实现方式/底层具体实现 首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。 ConcurrentHashMap 是由 Segment 数组结构和 HashEntry 数组结构组成。 Segment 实现了 ReentrantLock,所以 Segment 是一种可重入锁,扮演锁的角色。HashEntry 用于存储键值对数 据。

标签:面试题,hash,HashMap,JDK,常见,链表,线程,数组
From: https://www.cnblogs.com/w1366/p/17635524.html

相关文章

  • java面试题及答案(基础篇)
    如今IT仍是热门行业,面试程序员的人也非常多,那么,怎样才能顺利通过面试呢?2021最新java面试题及答案(基础篇),为你的面试助攻!1、Java中的内存溢出是如何造成的?OutOfMemoryError:(1)PerGernSpace程序中使用了大量jar或class,使Java虚拟机装载类空间不够。解决方案:调参XX:PermSize和XX:MaxP......
  • 服务器数据恢复-HP EVA存储原理&常见故障&数据恢复流程
    EVA存储原理:EVA系列存储是以虚拟化存储为实现目的的中高端存储设备,内部的结构组成完全不同于其他的存储设备,RAID在EVA内部称之为VRAID。EVA会在每个物理磁盘(PV)的0扇区写入签名,签名后PV会被分配到不同的DISKGROUP。在DISKGROUP中每个PV会按一定大小划分为若干存储单元(PP),PP的大小......
  • JVM相关面试题
    JVM的组成程序计数器Java堆虚拟机栈其实就是线程运行时需要的内存......
  • 常见客户登录命令
    常见客户登录命令1、telnet远程登录,文明登录telnet命令通常用来远程登录,要开始一个telnet会话,必须输入用户名和密码来登录服务器。telnet因为采用明文传送报文,安全性不好。telnet命令还可做别的用途,比如确定远程服务的状态,比如确定远程服务器的某个端口是否能访问。命令格式:tel......
  • php常见错误码
    php常见的错误码有:200:服务器响应正常。304:该资源在上次请求之后没有任何修改(这通常用于浏览器的缓存机制,使用GET请求时尤其需要注意)。400:无法找到请求的资源。401:访问资源的权限不够。403:没有权限访问资源。404:需要访问的资源不存在。405:需要访问的资源被禁止。407:访问的......
  • 2023前端JavaScript面试题大全
    一、基础题题目1:什么是JavaScript的数据类型?如何检查一个变量的数据类型?答案:JavaScript有七种数据类型:基本数据类型(PrimitiveDataTypes):Number、String、Boolean、Null、Undefined、Symbol引用数据类型(ReferenceDataTypes):Object、Array要检查一个变量的数据类......
  • 集合+hashmap
    数组数组(Array)是一种用连续的内存空间存储相同数据类型数据的线性数据结构。面试题:为什么数组索引从0开始?假如从1开始会怎么样?操作数组的时间复杂度当未知数组查询时,时间复杂度为O(n)总结———————————————————————————————————......
  • go语言编程常见问题
    在Goland中运行单元测试报错Error:Cannotfindpackage如下图,在Goland中运行单元测试时报错:“Error:Cannotfindpackage”弹出如下报错提示窗口:解决办法:在Goland设置界面中取消勾选“EnableGomodulesintegration”。参考:goland中运行go时报packagexxxisnotinGO......
  • 【校招VIP】java语言考点之ConcurrentHashMap1.7和1.8
    考点介绍:ConcurrentHashMap是JAVA校招面试的热门考点,主要集中在1.7和1.8的底层结构和相关的性能提高。理解这个考点要从map本身的并发问题出发,再到hashTable的低性能并发安全,引申到ConcurrentHashMap的分块处理。同时要理解读锁和写锁的区别一、考点题目1、ConcurrentHashMap与......
  • 【金九银十面试冲刺】Android岗面试题今日分享——Flutter篇
    又到了面试题分享的时间,今天分享的是Flutter方面的的面试题,总共包含以下板块:Dart部分Flutter部分话不多说,直接接上面试题!!!!Dart部分面试题一、Dart语言的特性?Productive(生产力高,Dart的语法清晰明了,工具简单但功能强大)Fast(执行速度快,Dart提供提前优化编译,以在移动设备和Web上获得可......