首页 > 其他分享 >HashMap的一些常见面试问题

HashMap的一些常见面试问题

时间:2023-08-07 22:58:40浏览次数:33  
标签:hash HashMap 16 常见 链表 面试 线程 数组 运算

HashMaph一些常见面试问题

一、hashmap底层如何实现的?

jdk1.7中通过数组+链表实现;jdk1.8中通过数组+链表+红黑树实现
它的主干是数组嘛,一个table数组
使用链表是为了解决哈希冲突嘛 所采用的链地址法
红黑树是为了避免链表过长导致的查询效率变低
它的一个底层存储原理是通过哈希表嘛
1.先创建一个默认长度为16,默认负载因子为0.75的数组,名为table
2.然后根据元素的hash值除以数组长度然后取余,余数值就是在数组中存储的位置
3.判断当前位置是否为空null,如果为null则直接存入
4.如果不为null则调用equals方法比较是否为同一个元素(不同元素的hash值取余后可能在同一位置),
不是同一个元素则存入数组(链表挂着),是同一个元素则不存(覆盖)
5.当数组存满到16*0.75=12的时候,就自动扩容,每次扩容到原来的两倍(左移一)
6.(jdk8以后(新元素挂在老元素后面))当数组长度大于等于64且链表长度大于8的时候自动转为红黑树,提高查找性能

二、寻址是怎么寻的?
i = (n - 1) & hash
用元素的hash值跟数组长度-1做与运算,实现取余操作(为什么不直接用%,因为计算机进行一些二进制运算会快很多)
举例:18->10010,16-1=15->1111 取余:10即2

三、hash函数怎么操作实现获取hash值的操作的?
在调用put方法的时候,会先调用hash函数,对原本元素的hash值进行一些处理
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
将获取到的hash值与这个获取到的哈希值右移16位后的数据做【异或】运算
(h=key.hashCode())^(h>>>16)//无符号右移
目的是为了减少哈希碰撞,
因为【存储的时候】都是跟数组长度length-1做【与运算】获取到的存储的下标的嘛
比如数组长度为16的时候-1=15二进制表示就是1111,做与运算只有低位有效了,
将获取到的hash值右移16位再做异或运算是为了让低位保留部分高位信息,从而减少哈希碰撞

四、为什么数组长度一直是2的整数幂?
第一:可以通过数组长度-1对元素的hash值进行与运算来【快速寻址】
(方便做与运算来快速寻址,因为对计算机来说做与运算要比做取余运算快很多)
第二:可以在扩容的时候保证【元素均匀分布】开来:如16扩容到32时,数组长度减一之后的二进制表示分别为1111和11111,再对hash值进行与运算时,前四位不变只看hash值的第五位是0还是1,而是0或是1的概率相等,所以会均匀分布开来。

五、初始化时hashmap的构造函数有指定容量的参数怎么实现的?
获取指定容量最近的2的整数幂的容量,进行右移1,2,4,8,16的操作然后进行或运算
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;//无符号右移
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

这个可以自行去用数据测试,比如14会变为16、18会变为32、5会变为8

六、HashMap线程不安全体现在哪里:

数据覆盖(进行put操作时):
1.寻址的时候嘛,线程A和线程B进行寻址时,定位到相同位置,而且该位置当前没有数据,线程A进行完if语句判断为null,准备插入时,它的时间片耗尽,导致只能将时间片给线程B来执行,由于A还没插入数据,所以线程B也判断为null,然后进行插入,插入完之后,时间片耗尽再给线程A,由于线程A之前已经判断了为空,所以直接插入,导致线程A的数据覆盖了线程B的数据。

2.判断是否需要扩容的时候也是同理,会导致两个线程都判断了,而size只加了1(假如原本size值为8,线程A在获取到size值后,时间片耗尽,cpu分配给线程B,线程B进行判断后size+1,当cpu再分配给线程A时,线程A会用最初获得的值8进行+1操作,故而造成两次put操作size只加了1)

标签:hash,HashMap,16,常见,链表,面试,线程,数组,运算
From: https://www.cnblogs.com/dsshl/p/17612959.html

相关文章

  • ArrayList底层原理、线程安全及其相关集合(面试常问)
    一、ArrayList底层原理1.特点及其原理:ArrayList底层基于数组实现,查找快,增删慢2.ArrayList底层原理,初始化及调用add()方法添加元素:默认初始化容量为10第一次创建集合并在添加第一个元素时在底层创建一个默认长度为10的数组:​调用构造函数初始化时默认创建的是空数组只......
  • 2023-8-7 记录一次面试题,使用Sql进行递归
     题目如图所示,是数据库源,这次考官需要我用Sql,完成一次数据查询需要根据Excel数据查询结果如上图,这时候我看到了父子关系,很容易就联想到了需要使用父子关系,既然是父子关系,一般来说应该递归跑不掉了,使用Sql进行递归代码如下:WITHTEST_CTEAS(SELECT地区表1.地区编号,地区......
  • 【金九银十面试冲刺】Android岗面试题每日分享——Java篇
    一、Java异常机制中,异常Exception与错误Error区别这道题想考察什么?在开发时需要时候需要自定义异常时,应该选择定义Excption还是Error?编写的代码触发Excption或者Error分别代表什么?考察的知识点Java异常机制考生应该如何回答在Java中存在一个Throwable可抛出类,Throwable有两个重要的......
  • 软件造价工程师培训考试常见问题
    (1-3个问题是针对想获取工业和信息化部教育与考试中心颁发软件工程造价师证书的解答。只获取联盟颁发的软件工程造价师证书的学员,可以忽略。)1、所有学员都要参加线上前置课程的学习吗?我是学软件工程专业毕业的,也是从事IT相关工作,对软件工程基础理论非常熟悉,是否可以免修?不可以。前......
  • 阿里云: web如何直传oss & 常见问题
    阿里云:web如何直传oss&常见问题 如何使用input.Type=‘file‘拿到文件对象1、在页面中添加<inputtype="file"style="display:none"ref="input"@input="upload">在需要上传文件的地方增加<button@click="$refs.input.click()">......
  • java笔试常见的选择题(坑你没商量)
    java笔试常见的选择题(坑你没商量)1.已知表达式intm[]={0,1,2,3,4,5,6};下面那个表达式的值与数组的长度相等()Am.length()B.m.lengthC.m.length()+1D.m.length+1答案:B分析:数组的长度是.length2.下面那些声明是合法的?()Alongl=4990B.inti=4LC.floatf=1.1D.doubled......
  • zookeeper常见问题解决
     注意:自zk3.5.5版本以后,已编译的jar包,尾部有bin标识,应该使用的是apache-zookeeper-3.x.x-bin.tar.gz 错误一:Startingzookeeper…FAILEDTOSTART版本问题,自3.5以上的版本,随着版本的更新,3.5版本以后的压缩包分成了两种我们需要使用文件名带有bin的那个压缩包,例如:ap......
  • Spring常见问题
    一、Spring是什么Spring是一个轻量级的IOC和AOP容器框架。是为Java应用程序提供基础服务的一套框架,目的是简化企业应用程序的开发,它使得开发者只需要关心业务需求。主要包含以下七个模块:1.SpringContext:提供框架式的Bean访问方式,以及企业级功能;2.SpringCore:核心类库,所有功能都......
  • 面试官:线程是如何通讯的?
    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。在Java中,线程等待和通知的实现手段有以下几种方式:Object类下的wait()、notify()和notifyAll()方法;Condition类下的await()、signal()和signalAll()方法;LockSupp......
  • #yyds干货盘点# LeetCode程序员面试金典:矩形区域不超过 K 的最大数值和
    1.简述:给你一个mxn的矩阵matrix和一个整数k,找出并返回矩阵内部矩形区域的不超过k的最大数值和。题目数据保证总会存在一个数值和不超过k的矩形区域。 示例1:输入:matrix=[[1,0,1],[0,-2,3]],k=2输出:2解释:蓝色边框圈出来的矩形区域 [[0,1],[-2,3]] 的数值和是......