HashMap 的数据结构
content
HashMap 的数据结构:
- 数组 + 链表(Java7 之前包括 Java7)
- 数组 + 链表 + 红黑树(从 Java8 开始)
PS:这里的《红黑树》与链表都是链式结构。
HashMap 内部维护了一个数组,数组中存放链表的链首或红黑树的树根。
当链表长度超过 8 时,链表就转换为红黑树,利用红黑树快速增删改查的特点提高 HashMap 的性能;在红黑树结点数量小于 6 时,红黑树转变为链表。
下面分别为上面两种数据结构的图示:
【定位算法】
增加、查找、删除等操作都需要先定位到 table 数组的某个索引处。
定位算法为三步:取 key 的 hashCode 值、高位运算、取模运算得到索引位置。(代码如下)
static final int hash(Object key) {
int h;
// h = key.hashCode() 第一步 取 hashCode 值
// h ^ (h >>> 16) 第二步 高位参与运算 Java8 优化了高位算法,优化原理忽略
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
// java7 中这是一个单独的方法,java8 没有了这个方法但是原理依旧
static int indexFor(int h, int length) {
return h & (length-1); // hash(key) & (length-1) 第三步 取模
}
取模运算h & (length -1)
的结果最大值为 length -1,不会出现数组下标越界的情况。
为什么要做高位运算?
如果 hashCode 值都大于 length,而且这些 hashCode 的低位变化不大,就会出现很多冲突,举个例子:
- 假设数组的初始化容量为 16(10000),则 length -1 位 15(1111)。
- 假设有几个对象的 hashCode 分别为 1100 10010、1110 10010、11101 10010,如果不做高位运算,直接使用它们做取模运算的结果将是一致的。
如果所有元素中多数元素属于这种情况,将会导致元素分布不均匀,而对 hashCode 进行高位运算能解决这个问题,使高位对低位造成影响改变低位的值,从而变相地使高位也参与运算。
append
【Q】负载因子与性能的关系
负载因子默认值为0.75
,意味着当数组实际填充量占比达到3/4
时就该扩容了。
负载因子越大,扩容次数必然越少,数组的长度越小,减少了空间开销;这就会导致 hash 碰撞越多,增加查询成本。
默认值0.75
在时间和空间成本上寻求一种折衷。
【Q】为什么要扩容
因为随着元素量的增大,hash 碰撞的概率越来越大,虽然使用链地址法能够解决存储问题,但是长长的链表会让 HashMap 失去快速检索的优势,而扩容能解决这个问题。
HashMap 的数据结构的更多相关文章
- Java中HashMap的数据结构
类声明: 概述: 线程不安全: <Key, Value>两者都可以为null: 不保证映射的顺序,特别是它不保证该顺序恒久不变: HashMap使用Iterator: HashMap中ha ...
- jdk1.8源码解析:HashMap底层数据结构之链表转红黑树的具体时机
本文从三个部分去探究HashMap的链表转红黑树的具体时机: 一.从HashMap中有关“链表转红黑树”阈值的声明: 二.[重点]解析HashMap.put(K key, V value)的源码: 三 ...
- HashMap底层数据结构详解
一.HashMap底层数据结构 JDK1.7及之前:数组+链表 JDK1.8:数组+链表+红黑树 关于HashMap基本的大家都知道,但是为什么数组的长度必须是2的指数次幂,为什么HashMap的加载 ...
- [转]java 的HashMap底层数据结构
java 的HashMap底层数据结构 HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-v ...
- java 的HashMap底层数据结构
HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-value总是会当做一个整体来处理,系统会根据 ...
- HashMap底层数据结构和算法解析
1.Hash Map的数据结构? A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点.当链表长度超过8时,链表转换为红黑树. transient Node<K,V>[] ta ...
- hashMap的数据结构
HashMap底层实现还是数组,只是数组的每一项都是一条链.
- jdk1.8 HashMap底层数据结构:深入解析为什么jdk1.8 HashMap的容量一定要是2的n次幂
前言 1.本文根据jdk1.8源码来分析HashMap的容量取值问题: 2.本文有做 jdk1.8 HashMap.resize()扩容方法的源码解析:见下文“一.3.扩容:同样需要保证扩容后的容量是 ...
- 探索HashMap实现原理及其在jdk8数据结构的改进
因为网上已经太多的关于HashMap的相关文章了,为了避免大量重复,又由于网上关于java8的HashMap的相关文章比较少,至少我没有找到比较详细的.所以才有了本文. 本文主要的内容: 1.Hash ...
随机推荐
- 「NOIP模拟赛」Round 2
Tag 递推,状压DP,最短路 A. 篮球比赛1 题面 \(Milky\ Way\)的代码 #include <cstdio> const int N = 2000, xzy = 1e9 ...
- 1.mysql读写
一.数据库读取(mysql) 参数 接受 作用 默认 sql or table_name string 读取的表名,或sql语句 无 con 数据库连接 数据库连接信息 无 index_col Int ...
- Java8的新特性--Optional
目录 Optional 一.Optional类是什么? 二.Optional类常用的方法 1. 创建Optional实例 1.1 Optional.of(T) 1.2 Optional.empty() ...
- Heron and His Triangle HDU - 6222
题目链接:https://vjudge.net/problem/HDU-6222 思路:打表找规律. 然后因为数据范围较大可以考虑用字符串模拟,或者__int128要注意用一个快读快输模板. 1 #i ...
- P1423_小玉在游泳(JAVA语言)
题目描述 小玉开心的在游泳,可是她很快难过的发现,自己的力气不够,游泳好累哦. 已知小玉第一步能游2米,可是随着越来越累,力气越来越小, 她接下来的每一步都只能游出上一步距离的98%. 现在小玉想知道 ...
- vscode远程连接linux服务器,可视化绘图
vscode远程连接linux服务器 想要实现的功能和解决方案 实现的功能: windows下直接使用远程linux服务器的python环境和文件来编写和运行py文件, 实时的编写py文件,和可视化绘 ...
- c++反汇编 switch
switch 线性处理 24: int nIndex = 0; 01377EBE C7 45 F8 00 00 00 00 mov dword ptr [nIndex],0 25: scanf(&qu ...
- PTA 统计二叉树度为2的结点个数
6-4 统计二叉树度为2的结点个数 (11 分) 本题要求实现一个函数,可统计二叉树中度为2的结点个数. 函数接口定义: int NodeCount ( BiTree T); T是二叉树树根指针, ...
- 等不及要告诉你的一件事-console.log可以指定样式
今天看`简书`文章,习惯性的打开了开发者工具,于是发现了意见有意思的事,在console面板,发现了如下的日志: ??? 这 ... 有点意思. 如果上面的图片,不能引起你的兴趣,那么你可以再看看这个 ...
- 1,turicreate入门 - jupyter & turicreate安装
turicreate入门系列文章目录 1,turicreate入门 - jupyter & turicreate安装 2,turicreate入门 - 一个简单的回归模型 3,turicrea ...