Java HashMap 面试题(一)

HashMap 面试题(一)

文章目录

  • HashMap 面试题(一)
    • 3.3 面试题-说一下HashMap的实现原理?
    • 面试题-HashMap的put方法的具体流程
      • hashMap常见属性
      • 源码分析

3.3 面试题-说一下HashMap的实现原理?

HashMap的数据结构: 底层使用hash表数据结构,即数组和链表或红黑树

  1. 当我们往HashMap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标

  2. 存储时,如果出现hash值相同的key,此时有两种情况。

a. 如果key相同,则覆盖原始值;

b. 如果key不同(出现冲突),则将当前的key-value放入链表或红黑树中

  1. 获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。

在这里插入图片描述

面试官追问:HashMap的jdk1.7和jdk1.8有什么区别

  • JDK1.8之前采用的是拉链法。拉链法:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。

  • jdk1.8在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8) 时并且数组长度达到64时,将链表转化为红黑树,以减少搜索时间。扩容 resize( ) 时,红黑树拆分成的树的结点数小于等于临界值6个,则退化成链表

面试题-HashMap的put方法的具体流程

hashMap常见属性

在这里插入图片描述

源码分析

在这里插入图片描述

  • HashMap是懒惰加载,在创建对象时并没有初始化数组

  • 在无参的构造函数中,设置了默认的加载因子是0.75

添加数据流程图
在这里插入图片描述

具体的源码:

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    //判断数组是否未初始化
    if ((tab = table) == null || (n = tab.length) == 0)
        //如果未初始化,调用resize方法 进行初始化
        n = (tab = resize()).length;
    //通过 & 运算求出该数据(key)的数组下标并判断该下标位置是否有数据
    if ((p = tab[i = (n - 1) & hash]) == null)
        //如果没有,直接将数据放在该下标位置
        tab[i] = newNode(hash, key, value, null);
    //该数组下标有数据的情况
    else {
        Node<K,V> e; K k;
        //判断该位置数据的key和新来的数据是否一样
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            //如果一样,证明为修改操作,该节点的数据赋值给e,后边会用到
            e = p;
        //判断是不是红黑树
        else if (p instanceof TreeNode)
            //如果是红黑树的话,进行红黑树的操作
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        //新数据和当前数组既不相同,也不是红黑树节点,证明是链表
        else {
            //遍历链表
            for (int binCount = 0; ; ++binCount) {
                //判断next节点,如果为空的话,证明遍历到链表尾部了
                if ((e = p.next) == null) {
                    //把新值放入链表尾部
                    p.next = newNode(hash, key, value, null);
                    //因为新插入了一条数据,所以判断链表长度是不是大于等于8
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        //如果是,进行转换红黑树操作
                        treeifyBin(tab, hash);
                    break;
                }
                //判断链表当中有数据相同的值,如果一样,证明为修改操作
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                //把下一个节点赋值为当前节点
                p = e;
            }
        }
        //判断e是否为空(e值为修改操作存放原数据的变量)
        if (e != null) { // existing mapping for key
            //不为空的话证明是修改操作,取出老值
            V oldValue = e.value;
            //一定会执行  onlyIfAbsent传进来的是false
            if (!onlyIfAbsent || oldValue == null)
                //将新值赋值当前节点
                e.value = value;
            afterNodeAccess(e);
            //返回老值
            return oldValue;
        }
    }
    //计数器,计算当前节点的修改次数
    ++modCount;
    //当前数组中的数据数量如果大于扩容阈值
    if (++size > threshold)
        //进行扩容操作
        resize();
    //空方法
    afterNodeInsertion(evict);
    //添加操作时 返回空值
    return null;
}
  1. 判断键值对数组table是否为空或为null,否则执行resize()进行扩容(初始化)

  2. 根据键值key计算hash值得到数组索引

  3. 判断table[i]==null,条件成立,直接新建节点添加

  4. 如果table[i]==null ,不成立

    4.1 判断table[i]的首个元素是否和key一样,如果相同直接覆盖value

    4.2 判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对

    4.3 遍历table[i],链表的尾部插入数据,然后判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操 作,遍历过程中若发现key已经存在直接覆盖value

  5. 插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold(数组长度*0.75),如果超过,进行扩容。

大家好,我是xwhking,一名技术爱好者,目前正在全力学习 Java,前端也会一点,如果你有任何疑问请你评论,或者可以加我QQ(2837468248)说明来意!希望能够与你共同进步

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/298891.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mongodb删除操作中字符序对结果的影响

本文还是要从删除操作的语法说起。 db.collection.deleteMany(<filter>,{writeConcern: <document>,collation: <document>,hint: <document|string>} ) 删除语法中&#xff0c;可以指定数据写入策略&#xff0c;字符序和使用的索引字段。 字符序&a…

2024--Django平台开发-Web框架和Django基础(二)

day02 Web框架和Django基础 今日概要&#xff1a; 网络底层引入&#xff0c;到底什么是web框架&#xff1f;常见web框架对比django快速上手&#xff08;创建网站&#xff09;常见操作&#xff1a;虚拟环境、django项目、多app应用、纯净版逐点剖析&#xff1a;路由、视图、模…

mysql的分页查询

我们来看下一段查询&#xff1a; select * from sys_role; 如果我们要进行分页查询&#xff0c;例如每页显示两条数据&#xff0c;我们可以利用 limit 关键字&#xff1a; select * from sys_role limit 0,2; select * from sys_role limit 2,2; 假设我们当前页面为 n&#xf…

机器学习--ROC AUC

参考 机器学习-ROC曲线 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/347470776一文看懂ROC、AUC - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/81202617 在了解之前&#xff0c;我们先来认识一下以下的概念 针对一个二分类问题&#xff0c;将实例分成正类(postive)或…

java基于SSM的游戏商城的设计与实现论文

基于SSM的游戏商城的设计与实现 摘 要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。以前相关行业对于游戏信息的管理和控制&#xff0c;采用人工登记的方式保存相关数据&#xff0c;这种以…

系统及应用安全

引导语 系统安全及应用是现代信息系统的核心组成部分&#xff0c;它不仅关乎信息安全&#xff0c;更直接影响到企业的运营效率、财务状况乃至品牌信誉。通过不断改进和强化系统的安全性&#xff0c;可以为企业创造一个更加可靠、高效的信息化环境。 一、账号安全的基本措施 …

狮子目标检测数据集VOC格式300张

狮子&#xff0c;作为“丛林之王”&#xff0c;以其威武雄壮的身姿和卓越的狩猎能力闻名于世。 狮子的体型健硕&#xff0c;毛发浓密&#xff0c;通常是金黄色或浅褐色&#xff0c;腹部和腿部的毛发相对较浅。狮子的头部特别大&#xff0c;长有一对威风凛凛的鬃毛&#xff0c;…

玩转Mysql 四(MySQL逻辑架构与数据引擎)

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。 一、MySQL逻辑架构 1、从Oracle收购MySQL后&#xff0c;MySQL逻辑架构受Oracle影响&#xff0c;MySQL8版本中逻辑架构受Oracle的影响逐步完善查询缓存&#xff0c;O…

多线程高级面试题

1. 什么是 ThreadLocal&#xff1f; 参考答案 ThreadLocal 叫做本地线程变量&#xff0c;意思是说&#xff0c;ThreadLocal 中填充的的是当前线程的变量&#xff0c;该变量对其他线程而言是封闭且隔离的&#xff0c;ThreadLocal 为变量在每个线程中创建了一个副本&#xff0c;…

2023年12月 C/C++(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:数的输入和输出 输入一个整数和双精度浮点数,先将浮点数保留2位小数输出,然后输出整数。 时间限制:1000 内存限制:65536 输入 一行两个数,分别为整数N(不超过整型范围),双精度浮点数F,以一个空格分开。 输出 一行两个数,分…

关于“Python”的核心知识点整理大全65

目录 20.2.19 设置 SECRET_KEY 20.2.20 将项目从 Heroku 删除 注意 20.3 小结 附录 A 安装Python A.1.1 确定已安装的版本 A.1.2 在 Linux 系统中安装 Python 3 A.2 在 OS X 系统中安装 Python A.2.1 确定已安装的版本 A.2.2 使用 Homebrew 来安装 Python 3 注意 …

[技术杂谈]使用VLC将视频转成一个可循环rtsp流

通过vlc播放器&#xff0c;将一个视频转成rtsp流&#xff0c;搭建一个rtsp服务器。rtsp客户端可访问这个视频的rtsp流。 1. 打开vlc播放器&#xff0c;使用的版本如下 2. 菜单&#xff1a;媒体 ---> 流 3. 添加视频文件&#xff0c;点击添加一个mp4 文件 4. 选择串流&…

【软件测试】学习笔记-测试覆盖率

测试覆盖率通常被用来衡量测试的充分性和完整性&#xff0c;从广义的角度来讲&#xff0c;测试覆盖率主要分为两大类&#xff0c;一类是面向项目的需求覆盖率&#xff0c;另一类是更偏向技术的代码覆盖率。 需求覆盖率 需求覆盖率是指测试对需求的覆盖程度&#xff0c;通常的做…

LeetCode 每日一题 Day 3334(hard)35 ||二进制枚举/单调栈/链表遍历

2397. 被列覆盖的最多行数 给你一个下标从 0 开始、大小为 m x n 的二进制矩阵 matrix &#xff1b;另给你一个整数 numSelect&#xff0c;表示你必须从 matrix 中选择的 不同 列的数量。 如果一行中所有的 1 都被你选中的列所覆盖&#xff0c;则认为这一行被 覆盖 了。 形式…

【CANopen】关于STM32中CanFestival的pdo应用

系列文章目录 文章目录 系列文章目录一、发送1、同步传输2、异步传输 二、接收 使用STM32F407单片机 pdo属于过程数据用来传输实时数据&#xff0c;即单向传输&#xff0c;无需接收节点回应。 一、发送 分为同步传输和异步传输。 1、同步传输 分为循环传输&#xff08;周期…

【Flink精讲】双流Join之Regular Join(即普通Join)

Regular Join 普通Join 通过条件关联两条实时数据流&#xff1a;动态表Join动态表支持Inner Join、Left Join、Right Join、Full Join。 1. Inner Join(Join)&#xff1a;只有两边数据流都关联上才输出[L,R] 2. Left Join(Left Outer Join)&#xff1a;只要左流有数据即输出[…

我的创作纪念日三年收获和感悟

机缘 我刚开始接触创作也是最近几年开始&#xff0c;当初就是希望自己的收获分享给大家&#xff0c;不仅使自己成长&#xff0c;也可以带着大家一起成长&#xff0c;独乐乐不如众乐乐&#xff0c;人都是自私的以前我都是看到好的知识文章都是自己藏起来&#xff0c;发现收获的…

python类的初始化

问题描述 存在这样的两个类&#xff0c;都在同一个模块a.py内 class YamlGlobal:with open(get_project_path() "/cfg/global.yaml", r, encodingutf-8) as f:glVar yaml.load(f, Loaderyaml.SafeLoader)......class DatabaseGlobal:itd InstanceDao(SQLAlchemy…

qml的操作 -- VS2022开发qml,

在使用VS开发软件的时候一般大型软件都会使用模组的方式。每个模组之间独立开发&#xff0c;关于qml写的UI模组也不例外&#xff0c;如果所有的qml都挤在一个文件夹下也不利于管理&#xff0c;维护起来也比较吃力。比较好的管理方法就是按照功能分布存放在不同的文件夹下。还有…

性能分析与调优: Linux 使用ELRepo升级CentOS内核

目录 一、实验 1.环境 2.agent 服务器使用ELRepo升级CentOS内核 二、问题 1. RHEL-7, SL-7 或者 CentOS-7系统如何安装ELRepo 2.RHEL-8或者RHEL-9系统如何安装ELRepo 一、实验 1.环境 &#xff08;1&#xff09;主机 表1-1 主机 主机架构组件IP备注prometheus 监测 系…