HashMap三两事
前言
JDK8中对HashMap做了优化,依然是用数组存储数据,但是扩容时采用双链表的方式避免了高并发情况下导致出现循环链表的问题,另外也引入了红黑树,提高碰撞元素的搜索速度。
一段代码
下面这段代码创建一个容量为64的HashMap和插入一些数据。
HashMap<Integer,Integer> hashMap=new HashMap<>(64);
hashMap.put(5,5);
hashMap.put(2,2);
hashMap.put(69,69);
hashMap.put(66,66);
hashMap.put(325,325);
hashMap.put(197,197);
hashMap.put(261,261);
hashMap.put(133,133);
hashMap.put(389,389);
hashMap.put(453,453);
hashMap.put(133,999);
如何定位数据下标
一开始说到HashMap是用数组来存储数据,那么数组下标和key是怎么关联上的呢。其实它是将key的hash值和数组长度进行一系列的位运算(异或和与)得出数据下标。例如key=69时,运算如下

最后得出下标是5,那就把(69,69)包装成Node<Integer,Integer>放在数组5的位置上。
链表
从上面公式可以看到,大小相差64的key计算出来的位置都是一样的,例如5和69计算出来的下标都是5,产生冲突了。数组一个下标只能存储一个元素,那么怎么办。HashMap这个时候会用链表来存储冲突的元素,第一个存储在数组的就是链表头Node,接下来冲突元素放在链表头Node的Next位置上,上面那段代码执行流程如下:

从上面的动图可以看到,每个元素都是链表顺序往下找,如果找到相同key的元素,就替换value,否者就放在链表的尾元素的next上。那么问题来了,如果链表很长,每次都要一直遍历到尾部,这太耗时了,时间复杂度为O(n)。如果将链表改成红黑树,那么时间复杂度将会是O(logn)。事实上,HashMap就是这么干的。
红黑树
在HashMap中,当链表长度大于8时,链表将会转成红黑树。而红黑树的根会存储在数组中。如果这个时候再put一个元素(517,517),将会触发树转换,最终转换的结果如下

在说转换之前,可以先来了解一下红黑树的概念。其实红黑树是近似二叉平衡树的,二叉平衡树又是二叉树的一种,他们之间的关系如下

我个人觉得从二叉搜索树开始,在计算机科学中才有一定价值。每一种树都有性质,性质是继承的,越里面的树性质越多。
- 二叉搜索树:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
- 平衡二叉搜索树:在二叉树的基础上,加上性质:它的左右两个子树的高度差的绝对值不超过1。平衡二叉搜索树搜索复杂度总是O(logn),有效规避了有序元素插入的情况导致退化成链表的问题。
- 红黑树:在二叉搜索树的基础上,加入四个性质,使树总是保持近似平衡,搜索时间复杂度也是O(logn)。
1. 节点是红色或黑色。
2. 根节点是黑色。
按照红黑树的性质,每次新插入的都是在树的最下面,为红叶子,因为红叶子可能都不用调整,黑叶子100%要调整。从上面的流程图可以看到,调整都是从新增的红叶子开始的,通过变色或者左旋右旋的操作不断向上调整,直到调整到根节点。
HashMap三两事的更多相关文章
- [转]关于AS3 Socket和TCP不得不说的三两事
磨刀不误砍柴工,让我们从概念入手,逐步深入. 所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络 ...
- Spring配置之标签的三两事
今天看到项目的配置,看后就当是复习了.懵懵懂懂工作两年,感觉虽然自己一直在使用spring作为工具,但是也没有涉及到spring的方方面面,今天的研究从一次无意的自动补全开始,还是那句话,不爱研究的程 ...
- vue打包之部署在非根路径下的三两事
首先,感叹一下,2019年已经过去一半,想想自己做了些什么,好像也没做什么. 今天试着配一个nginx,以前的nginx都是指向的/根路径,今天的nginx指向的非/根路径,遇到许多问题的,总结总结. ...
- C++:MEMSET的大坑三两事
之前写了一题费用流,竟然硬是在写SPFA时为DIS数组赋初始值用了MEMSET数组QAQ 调试了很久也没有弄明白自己是卡在那里了,,,感觉被自己蠢哭了QWQ 错误的姿势!! #include < ...
- nodejs之mock与跨域代理的三两事
emmm...好久没写博客了,都忘了该怎么开始. 那就先说下mockjs.因为一些原因,导致后台接口没有数据,那么我们就开始自己造数据,使用的是比较流行mockjs,根据文档就能简单的配置,然后开始愉 ...
- iad 集成三两事
1. 好像是随着ios8的beta开始. iad 已经发生了一些变化. 比如找不到enable iad network 的按钮了. 貌似是不需要手动去 enable 了. 只需要嵌入 iad fra ...
- 微信小程序:开发之前要知道的三件事
前言 微信之父张小龙在年初的那次演讲中曾表示:"我自己是很多年的程序员,我觉得我们应该为开发的团队做一些事情".几个月后,微信正式推出微信应用号(即微信小程序),在互联网中掀起了又 ...
- <转>离婚前夜悟出的三件事
文/铁眼(简书作者)原文链接:http://www.jianshu.com/p/832be4f659a0?utm_campaign=hugo&utm_medium=reader_share&a ...
- day16模块,导入模板完成的三件事,起别名,模块的分类,模块的加载顺序,环境变量,from...import语法导入,from...import *,链式导入,循环导入
复习 ''' 1.生成器中的send方法 -- 给当前停止的yield发生信息 -- 内部调用__next__()取到下一个yield的返回值 2.递归:函数的(直接,间接)自调用 -- 回溯 与 递 ...
随机推荐
- 公众平台第三方平台 .NET开发
前言:本博客借鉴了很多三方内容整理的,参考博客:竹叶苿. 一.开发的目的(以下是引用官方的话) 公众平台第三方平台 是为了让公众号或小程序运营者,在面向垂直行业需求时,可以一键授权给第三方平台(并且可 ...
- 5.Struts2-Struts标签
通用标签 1.property(取值) property:<s:property value="username"/> property 取值为字符串:<s:pr ...
- pycharm问题合集
一 打开pycharm出现 点击右上角的配置之后 配置正确的python路径 又出现 解决办法 删除所有的解释器,据说是重名导致的. 然后在配置一次 二 ModuleNotFoundError: ...
- MacBook Pro实现共享屏幕(多台mac之间)
1 开启允许所有用户控制屏幕 设置— 共享 2 在另一台MacBook Pro里打开finder窗口,并设置好network显示边栏 3 另一台机器发送请求控制 找 ...
- C++ 新特性 笔记 2 右值引用
C ++ Rvalue引用说明 以下内容,主要是上述链接的摘要 介绍 Rvalue引用是C ++的一个特性,它是随C ++ 11标准添加的.使右值参考有点难以理解的是,当你第一次看到它们时,不清楚它们 ...
- DA_04_解决Xshell中文乱码问题
一:解决Xshell中文乱码问题 二:解决克隆后eth0不见的问题 2.1:虚拟机克隆步骤: 1.直接修改 /etc/sysconfig/network-script/i ...
- sum(n,m)的解法
给出两个整数n和m,你应该计算从n到m的所有整数的和.换句话说,你应该计算: SUM(n,m)= n +(n + 1)+(n + 2)+ ... +(m-1)+ m 方法1. 方法2.
- Pyspark常用API总结
DF 类似于二维表的数据结果 mame age 狗山石 23 获取df的列名: df.columns 显示当前值 打印 df.show() show(2) show括号里面传入参数可以显示查看几行 s ...
- Selenium(3)
练习1:Ecshop 录制登录后退出业务 打开系统 存储页面的标题 a.点击"登录"按钮 b.输入用户名:testing 存储输入的用户名 c.输入密码:123456 d.点击&q ...
- 【BZOJ 3514】Codechef MARCH14 GERALD07 加强版
题意 \(n\) 个点 \(m\) 条边的无向图,\(k\) 次询问保留图中编号在 \([l,r]\) 的边的时候图中的联通块个数.强制在线. \(n,m,k\le 2\times 10^5\) 题解 ...