当前位置: 首页 > news >正文

HashMap剖析之内部结构

前言

本文是基于Java 8HashMap进行分析,主要是介绍HashMap中的成员变量和类变量的用途,以及分析HashMap的数据结构。

变量分析

HashMap中存在多个成员变量和类变量,搞清楚它们的用途有助于我们更深入了解HashMap,下面是它们的介绍:

    /**
     * 默认的初始容量,值为2的4次方
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 众所周知是16

    /**
     * 最大容量
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * 默认的负载因子
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * 将链表转化为红黑树的阈值,当链表节点数大于或等于该阈值-1则转化为红黑树
     */
    static final int TREEIFY_THRESHOLD = 8;

    /**
     * 将红黑树转化为链表的阈值,当红黑树的节点小于该阈值时转化为链表
     */
    static final int UNTREEIFY_THRESHOLD = 6;

    /**
     * 允许进行链表转化为红黑树的阈值,只有散列表大小大于或等于该值才能进行红黑树转化
     */
    static final int MIN_TREEIFY_CAPACITY = 64;
    /**
     * HashMap中存储数据的数组,也称为散列表。
     * 长度为2的N次幂
     */
    transient Node<K,V>[] table;

    /**
     * 缓存entrySet()方法的值
     */
    transient Set<Map.Entry<K,V>> entrySet;

    /**
     * Map中键值对的个数
     */
    transient int size;

    /**
     * HashMap数据结构被改变的次数,一般是指散列表的长度改变、Node链表增加或者减少节点
     * 这个参数是用于快速失败机制
     */
    transient int modCount;

    /**
     * 下一次触发调整大小(resize()方法)的阈值,一般为容量乘以负载因子 
     */
    int threshold;

    /**
     * 散列表的负载因子,用于计算扩容的阈值
     */
    final float loadFactor;

数据结构

HashMap使用拉链法解决哈希表中存在的哈希冲突问题,所以HashMap底层是用以NodeJava 7名称是Entry)组成的链表为元素的数组table来存储键值对,每个Node就是一个键值对对象。table称呼为散列表。

table对应的是散列表,是因为无论是存储还是读取键值对的时候,都会对key进行hash%table.length运算来进行散列表的命中,然后操作命中的索引对应的Node链表(还是会比较keyhash)。

以上为Java 8之前版本的HashMap的实现,而Java 8进行了优化:就是当链表节点数超过阈值TREEIFY_THRESHOLD(8)时,则会将链表转化为红黑树

如果只是使用文字描述的话会很难理解,所以下面会通过一幅图展示:

Java1.8的HashMap内部结构简图

相关文章:

  • OpenvSwitch/OpenFlow 架构解析与实践案例
  • CSS opacity设置不透明度
  • runC爆严重安全漏洞,主机可被攻击!使用容器的快打补丁
  • CH5102 Mobile Service
  • 区块链共识机制优缺点对比都是什么
  • Python数据可视化的10种技能
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • sql语句实战
  • 小程序微服务单个SSL证书部署多个项目解决方案
  • Async注解的使用,异步进行代码解耦
  • 我们在编写python代码时应该注意那几件事 !
  • Collection和Collections的区别是什么?
  • 根据出生日期计算年龄
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • centos7系统安装完成初始化
  • 【附node操作实例】redis简明入门系列—字符串类型
  • ES6简单总结(搭配简单的讲解和小案例)
  • Github访问慢解决办法
  • JavaScript实现分页效果
  • passportjs 源码分析
  • Python 基础起步 (十) 什么叫函数?
  • Rancher如何对接Ceph-RBD块存储
  • text-decoration与color属性
  • vue--为什么data属性必须是一个函数
  • 电商搜索引擎的架构设计和性能优化
  • 区块链技术特点之去中心化特性
  • 入手阿里云新服务器的部署NODE
  • 无服务器化是企业 IT 架构的未来吗?
  • 用Canvas画一棵二叉树
  • ​Linux·i2c驱动架构​
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • #pragma once
  • (3)选择元素——(17)练习(Exercises)
  • (done) 两个矩阵 “相似” 是什么意思?
  • (function(){})()的分步解析
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (转)socket Aio demo
  • (转)我也是一只IT小小鸟
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • ./configure,make,make install的作用(转)
  • .bashrc在哪里,alias妙用
  • .NET MVC第五章、模型绑定获取表单数据
  • .NET 常见的偏门问题
  • .NET 的程序集加载上下文
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .net开发时的诡异问题,button的onclick事件无效
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)
  • .NET序列化 serializable,反序列化
  • .Net中wcf服务生成及调用
  • []常用AT命令解释()
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用
  • [BPU部署教程] 教你搞定YOLOV5部署 (版本: 6.2)
  • [BZOJ 3282] Tree 【LCT】