HashMap源码追踪

Python源码阅读技巧 刚参加工作那会,没想过去读源码,更没想过去改框架的源码;总想着别人的框架应该是完美的、万能的,应该不需要改;另外即使我改了源码,怎么样让我的改动生效了?项目中引用的不还是没改的jar包吗。回想起来觉得那时候的想法确实挺…… 工作了一年多之后准备跳槽了,开始了一轮的面试,其中有几个面试官就问到了相关的源码问题:ArrayList、HashMap的底层实现,spring、mybatis的相关源码。问... 阅读详情

1.HashMap简介

HashMap作为开发中使用频率比较高的容器类,对HashMap底层原理的理解。有利我们写出质量更高的代码,提升系统的性能。

2.从类的层次看HashMap

  • HashMap实现Map接口,属于集合框架中Map的一种实现,主要使用key和value存储数据。存储的元素key是不可以重复,重复的情况下,进行覆盖。
  • HashMap 属于线程不安全的类,在并发的情况下。同一时刻同一个HashMap,一个线程向HashMap 中put元素,另一个线程迭代HashMap中的元素会产生fast fail。程序会抛出异常。

3.构造函数以及常用的Api

3.1 构造函数
   /**
     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
     * (16) and the default load factor (0.75).
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }

无参构造函数,初始化HashMap哈希表默认的长度为16 负载因子为0.75

  /**
     * Constructs an empty <tt>HashMap</tt> with the specified initial
     * capacity and the default load factor (0.75).
     *
     * @param  initialCapacity the initial capacity.
     * @throws IllegalArgumentException if the initial capacity is negative.
     */
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

有参构造函数,initalCapacity用于初始化哈希表的长度,负载因子的初始化0.75。由于哈希表需要扩容,所以能够确定HashMap中存储数据多少的情况之下。创建HashMap的时候,建议指定HashMap的大小。

 /* ---------------- Public operations -------------- */

    /**
     * Constructs an empty <tt>HashMap</tt> with the specified initial
     * capacity and load factor.
     *
     * @param  initialCapacity the initial capacity
     * @param  loadFactor      the load factor
     * @throws IllegalArgumentException if the initial capacity is negative
     *         or the load factor is nonpositive
     */
    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }

可以指定HashMap初始化哈希表的长度,和负载因子的大小。由于负载因子0.75 刚好效率最好,开发中一般不建议,指定负载因子的大小。

  /**
     * Constructs a new <tt>HashMap</tt> with the same mappings as the
     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
     * default load factor (0.75) and an initial capacity sufficient to
     * hold the mappings in the specified <tt>Map</tt>.
     *
     * @param   m the map whose mappings are to be placed in this map
     * @throws  NullPointerException if the specified map is null
     */
    public HashMap(Map<? extends K, ? extends V> m) {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        putMapEntries(m, false);
    }

传入实现Map的集合类,可以完成集合中数据的复制。

3.2 常用api
3.2.1 HashMap 主要用于数据的增删改查,所以常用的Api主要按照增删改查进行分类
  1. 增加元素: put(K key, V value),putAll(Map<? extends K, ? extends V> m)
  2. 删除元素:remove(Object key),remove(Object key, Object value),clear()清空元素
  3. 修改元素:值覆盖的方式修改value,直接使用put(K key, V value)方法,replace(K key, V value),replace(K key, V oldValue, V newValue)。
  4. 查询:(1)查询容器本身:size(),isEmpty(),(2)查询容器中的元素:get(Object key), entrySet() , keySet(),values() 。

4. 源码追踪

4.1 put 元素的过程
  /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
     */
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

(1)put元素的时候,先根据key计算,存储元素所在哈希表中的下标。key为null时存储的下标为0,通过key的hashcode进行计算后,得出下标。这种计算得到的下标冲突比较的少。但是也有可能产生下标的冲突。
下标冲突之后,通过下标中的链表解决冲突的问题。

(2)扩容问题:负载因子大小对扩容的影响
负载因子越小,由key计算的哈希表的下标冲突的可能性越小,扩容的次数越多
负载因子越大,由key 产生的哈希表的下标冲突的可能性越大,扩容的次数越小

5. 这么重要的类,JDK 肯定在不停的优化它

  1. Java8中对于hash冲突,哈希表中同一个下标的元素,超过8的,不在使用链表的数据结构进行存储,直接使用红黑树进行存储数据。
    2.红黑树数据结构:比较不错的红黑树文章

6.使用HashMap注意问题总结

  1. 扩容很消耗性能,确定HashMap存储元素的多少时候,初始HashMap 时候指定大小。
  2. HashMap 是线程不安全的类,多线程的情况下,容易造成死循环。导致Cpu飙升。
飞腾X100芯片GPU状态查询 本文档对在linux系统下查看X100芯片GPU状态信息进行说明,可以帮助大家了解芯片的实时工作状态。 阅读详情

相关推荐

告别手动刷金币:零代码配置实现番茄小说自动化任务

本文详细介绍如何利用零代码配置工具实现番茄小说自动化任务,告别手动刷金币的烦恼。通过冰狐智能辅助工具的可视化配置和元数据复用功能,用户无需编程基础即可快速设置自动签到、观看广告等任务流程,大幅提升效率并避免断签风险。

weixin_42522953的博客 295

【Java】HashMap实现原理分析(源码分析,ReHash,扩容机制)

目录 一、HashMap的数据结构 解决hash冲突的办法 二、源码分析 1.位桶数组 2.数组元素Node实现了Entry接口,v> 3.HashMap如何put(key,value) 4.HashMap如何getValue值 5.HasMap的扩容机制resize(); 6. JDK1.8使用红黑树的改进 三、再谈ReHash 单线程下的ReHash ...

康师傅没有眼泪 4582

如何在Ubuntu 22.04上为AlphaFold3配置NVIDIA A100 GPU(含驱动安装避坑指南)

本文提供了在Ubuntu 22.04系统上为AlphaFold3部署NVIDIA A100 GPU的完整安装教程。内容涵盖从系统环境准备、NVIDIA驱动安装与避坑指南,到Docker容器化部署、数据库获取以及最终构建运行AlphaFold3的详细步骤,旨在帮助研究者和开发者高效配置高性能计算环境,充分发挥A100的硬件潜力。

nft7creator的博客 468

JDK1.8的HashMap的源码跟踪及底层实现

JDK1.8的HashMap的底层实现:数组+链表/红黑树 几个常量和变量: (1)DEFAULT_INITIAL_CAPACITY:默认的初始容量 16 (2)MAXIMUM_CAPACITY:最大容量 1 << 30 (3)DEFAULT_LOAD_FACTOR:默认加载因子 0.75 (4)TREEIFY_THRESHOLD:默认树化阈值8,当链表的长度达到这个值后,要考虑树化 (5)UNTREEIFY_THRESHOLD:默认反树化阈值6,当树中的结点的个数达到这个阈值后,要考虑变为

Marblue_的博客 223

易智联LM401模块学习(一)——初识Lora

Lora

weixin_46046597的博客 1054

手把手教你用FreeModbus RTU协议栈实现STM32与PLC通信(附Keil工程)

本文详细介绍了如何使用FreeModbus RTU协议栈在STM32上实现与PLC的工业通信。从环境搭建、工程配置到关键移植接口实现,提供了Keil工程模板和调试技巧,帮助开发者快速掌握Modbus RTU通信技术,适用于工业自动化领域的设备间通信需求。

weixin_42549037的博客 418

关于调试HashMap源码的小心得(这篇是我耗费了断断续续两天才得出来的)

先说说大体的情况: 我用的idea,在阅读HashMap的源码时候,我大体看懂了。但整体的一个数据具体储和流程我想用idea去走下断点,然后我就在自己的springboot项目里写了个测试类,然后简简单单、板板正正的new HashMap,然后put一下,get一下。然后我就点debug按钮开始执行了。然后很顺利的渗透到HashMap的内部,但TM遇到了一个骚问题(请允许我用一个艹),如下: ...

vigoss77的博客 1433

iSLIP算法实战:如何用Python模拟交换机优先级匹配(附完整代码)

本文详细介绍了如何使用Python实现iSLIP算法,模拟交换机优先级匹配过程。通过核心的指针滑动逻辑和迭代循环策略,构建了一个完整的iSLIP算法模拟器,并加入可视化模块以直观展示匹配过程。文章还提供了完整的代码框架和性能优化建议,适合网络工程师和Python开发者直接集成到测试环境中。

weixin_29313239的博客 249

HashMap源码分析

此文章系作者原创,转载请标明:https://www.cnblogs.com/yanfei1819/p/9989272.html 一、数据模型 ​ 在网上看过一些所谓的HashMap源码分析,大部分依旧是比较抽象的。究其原因,主要还是对HashMap的数据结构不理解。以下以图示展示。 HashMap中存在一个内部类: static class Node<K,V> implem...

weixin_30511039的博客 241

AMD KFD的SDMA Packet 类型和定义解析

本文详细分析了AMD GPU架构中的SDMA(System Direct Memory Access)数据传输机制,重点介绍了其核心数据结构——SDMA Packet。SDMA通过8种主要Packet类型(包括内存拷贝、数据写入、屏障同步、中断触发等)实现高效主机-设备通信。每种Packet采用位域结构和联合体封装设计,在保证功能完整性的同时实现空间优化。这些Packet支持丰富的访问属性和扩展字段,适用于高性能数据搬运、内存初始化、任务同步、性能分析等场景,为GPU计算提供了灵活高效的数据传输解决方案。

图形/计算GPU的驱动与虚拟化技术分享园地 1243

【即插即用模块】注意力篇 | TGRS 2025 | CDFIM:通道+空间多尺度注意力,双模态特征融合增强,性能翻倍!

C2DFF-Net提出了一种轻量级跨模态特征融合模块CDFIM,通过模态差异感知和多尺度深度滤波增强双模态互补信息。该模块采用通道-空间注意力协同机制,以极低计算成本(仅增加0.26M参数)提升多模态目标检测性能,在三个遥感数据集上平均提升mAP约1.7%。适用于无人机等边缘设备的实时检测任务,为跨模态融合提供高效解决方案。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 623

HashMap(深入源码追踪)

一篇让你搞懂HashMap的几个最重要的知识点,往源码跟踪可以让我们很轻松应对所谓的一些八股面试题.

m0_65013257的博客 1158

通过WorkVisual连接KUKA机器人的具体方法

通过WorkVisual连接KUKA机器人的具体方法

Robot_PLC_HMI_Automation 6842

JDK1.8中HashMap源码追踪

几个常量 默认初始容量:default_initial_capacity=(1<<4)=16 最大容量:maximum_capacity=(1<<30); 树化阈值:treeify_threshold=8:当链表的长度达到这个数值后,要考虑树化 反树化值:untreeify_threshold=6:当树中的节点个数达到这个阈值之后,要考虑变为链表。 最小树化容量:min_treeify_capacity=64。 单个链表的节点个数达到8且table的长度达到64,会...

weixin_43868322的博客 215

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

HashMap源码追踪(1.8版本)——put方法流程追踪、扩容resize()、树化treeifyBin()

put方法流程追踪 1、put public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } 进入resize方法 2、resize 图1 新的阈值 创建数组,赋值给table属性 图2 回到put方法,根据计算获取数组下标位置,并从table数组中取出Node节点 如果不存在则创建新的节点对象 图3 第一次resize是进行了table的初始化赋值,此时进

luoxiaomei999的博客 256

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java进阶必备:深入解析LinkedHashMap的原理与实战应用(非常详细)从零基础到精通,收藏这篇就够了!

★说白了,LinkedHashMap 就是 HashMap 的一个“亲儿子”,但它不安分,非要在老爹的基础上,自己搞了条“双向锁链”,说是什么要记住兄弟们(键值对)是按先来后到排队的,还是谁最近被“翻牌子”了。跟那个随心所欲、不记顺序的 HashMap 比起来,LinkedHashMap 这小子,嘿,它还真就能把元素塞进去的顺序,或者你最近摸过哪个元素的顺序给捋得清清楚楚。不信?瞧见没?,明明白白。

A1_3_9_7的博客 921

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

十年腾讯高级架构师,阅读代码的正确打开方式

读源码的经历 刚参加工作那会,没想过去读源码,更没想过去改框架的源码;总想着别人的框架应该是完美的、万能的,应该不需要改;另外即使我改了源码,怎么样让我的改动生效了? 项目中引用的不还是没改的jar包吗。回想起来觉得那时候的想法确实挺无知的。 小编从事在线教育多年,将自己的资料整合建了一个QQ群,对于有兴趣一起交流学习java的可以加群:732976516,里面有大神会给予解答,也会有许多的资...

weixin_43923408的博客 531

杂谈篇之我是怎么读源码的,授之以渔

转自:https://www.cnblogs.com/youzhibing/p/9553752.html 以下为原文。 读源码的经历   刚参加工作那会,没想过去读源码,更没想过去改框架的源码;总想着别人的框架应该是完美的、万能的,应该不需要改;另外即使我改了源码,怎么样让我的改动生效了? 项目中引用的不还是没改的jar包吗。回想起来觉得那时候的想法确实挺......   工作了一年多之后...

ligeforrent的专栏 296

如何学会阅读源码

优质文章,及时送达作者 | youzhibing链接 | cnblogs.com/youzhibing/p/9553752.html读源码的经历刚参加工作那会,没想过去读源码,更没想过去改框架的源码;总想着别人的框架应该是完美的、万能的,应该不需要改;另外即使我改了源码,怎么样让我的改动生效了?项目中引用的不还是没改的jar包吗。回想起来觉得那时候的想法确实挺……工作了一年多之后准备跳槽了,开始了...

公众号:Java后端 233

如何学会阅读源码?

作者 | youzhibing链接 | cnblogs.com/youzhibing/p/9553752.html1.读源码的经历刚参加工作那会,没想过去读源码,更没想过去改框架的源码;...

磊哥聊Java 409

IDEA插件:SequenceDiagram源码自动生成时序图

IDEA -->setting -> plugins ->market搜索:SequenceDiagram,下载好后重启即可

不是秋刀鱼的秋的博客 1208

我是怎么读源码的,授之以渔

本文经由博客园作者青石路授权转载原文地址:https://www.cnblogs.com/youzhibing/p/9553752.html如需转载请联系原作者读源码的经历刚参加工作...

JAVA高级架构 280

阿里十年架构师教你如何学会阅读源码

读源码的经历 刚参加工作那会,没想过去读源码,更没想过去改框架的源码;总想着别人的框架应该是完美的、万能的,应该不需要改;另外即使我改了源码,怎么样让我的改动生效了? 项目中引用的不还是没改的jar包吗。回想起来觉得那时候的想法确实挺…… 工作了一年多之后准备跳槽了,开始了一轮的面试,其中有几个面试官就问到了相关的源码问题:ArrayList、HashMap的底层实现,spring、mybat...

weixin_44174165的博客 278
上一篇: elasticsearch之旅----------------Linux中安装部署
下一篇: 有了ThreadPoolExecutor,还有Thread什么事
RollingInTheDeepc
博客等级 码龄9年 10粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值