JDK1.8 的 HashMap 源码之注意事项
英语渣靠着翻译插件,大概翻译的,难免有错误之处,注意甄别;
链表变树
This map usually acts as a binned (bucketed) hash table, but
when bins get too large, they are transformed into bins of
TreeNodes, each structured similarly to those in
java.util.TreeMap. Most methods try to use normal bins, but
relay to TreeNode methods when applicable (simply by checking
instanceof a node). Bins of TreeNodes may be traversed and
used like any others, but additionally support faster lookup
when overpopulated. However, since the vast majority of bins in
normal use are not overpopulated, checking for existence of
tree bins may be delayed in the course of table methods.
HashMap
通常表现为一张哈希表,每个桶里面放一个元素,当有多个元素的时候,变为链表,这时候每个桶里面都是放链表;但是当链表的长度达到一个临界的时候,链表转换为树,每个树的结构就像 TreeMap
一样,这时候,每个桶里面就是一个树形结构;
大多数方法只是用普通的桶,即里面只是链表;但是在合适的时候,链表会被转为树,比如检查每个节点的时候;因为这时候转换为树,不但支持原来链表的遍历和使用,同时还能获得更快的查找;
但是由于大多数时候,每个桶都没有被过度填充,即里面都是链表,还达不到转换为树的条件,因此 HashMap
的方法可能会延迟检查桶里面到底是链表还是树形结构 ;
树形结构与Comparable,性能极致与降低
Tree bins (i.e., bins whose elements are all TreeNodes) are
ordered primarily by hashCode, but in the case of ties, if two
elements are of the same "class C implements Comparable",
type then their compareTo method is used for ordering. (We
conservatively check generic types via reflection to validate
this -- see method comparableClassFor). The added complexity
of tree bins is worthwhile in providing worst-case O(log n)
operations when keys either have distinct hashes or are
orderable, Thus, performance degrades gracefully under
accidental or malicious usages in which hashCode() methods
return values that are poorly distributed, as well as those in
which many keys share a hashCode, so long as they are also
Comparable. (If neither of these apply, we may waste about a
factor of two in time and space compared to taking no
precautions. But the only known cases stem from poor user
programming practices that are already so slow that this makes
little difference.)
当桶里面的结构是树形结构的时候,通常情况下是按照 HashCode
来算下标位置的;但是如果要插入的元素实现了 Comparable
接口,则使用接口的 compareTo
方法,计算排序的位置 ;
树形结构(HashMap
中的树是红黑树)保证了在元素具有 不同的哈希码或者可以排序 的情况下,插入元素复杂度在最坏的情况下是 O log(n)
,因此,将桶中的链表在一定情况下转成树是值得的;
因此,如果恶意的将 hashCode
方法的返回值故意分布在一起,比如返回同一个哈希码,或者实现了 Comparable
接口,但是 compareTo
永远返回 0
,这时候 HashCdoe
的性能会下降 ;
如果这两种方法都不适用(不同的哈希码或者可以排序),与不采取预防措施相比,我们可能会浪费大约两倍的时间和空间。但目前所知的唯一案例源于糟糕的用户编程实践,这些实践已经非常缓慢,以至于没有什么区别;
链表与树之间转换的阈值
Because TreeNodes are about twice the size of regular nodes, we
use them only when bins contain enough nodes to warrant use
(see TREEIFY_THRESHOLD). And when they become too small (due to
removal or resizing) they are converted back to plain bins. In
usages with well-distributed user hashCodes, tree bins are
rarely used. Ideally, under random hashCodes, the frequency of
nodes in bins follows a Poisson distribution
(http://en.wikipedia.org/wiki/Poisson_distribution) with a
parameter of about 0.5 on average for the default resizing
threshold of 0.75, although with a large variance because of
resizing granularity. Ignoring variance, the expected
occurrences of list size k are (exp(-0.5) * pow(0.5, k) /
factorial(k)).
因为树节点的大小大约是普通节点的两倍,所以我们只在桶中包含足够的节点(TREEIFY_THRESHOLD = 8
)时才进行链表转换成树的操作;
当树因为删除节点变得很小的时候,会再次转换回链表;
如果 HashCode
方法设计的很好的话,哈希冲突降低,链表的长度基本就不会很长,树是很少用到的;
理想情况下,随机的哈希码,遵循 Poisson
(泊松)分布;
下面还有一些,粗略看了下,没有什么震撼的信息,就不在翻译了;
看源码,英文注释,也很费时间啊
JDK1.8 的 HashMap 源码之注意事项的更多相关文章
- 基于jdk1.8的HashMap源码学习笔记
作为一种最为常用的容器,同时也是效率比较高的容器,HashMap当之无愧.所以自己这次jdk源码学习,就从HashMap开始吧,当然水平有限,有不正确的地方,欢迎指正,促进共同学习进步,就是喜欢程序员 ...
- JDK1.7之 HashMap 源码分析
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/75451812 类继承关系 构造函数 Entry put put putForNullK ...
- Java集合(七)--基于jdk1.8的HashMap源码
HashMap在开发中经常用,面试源码方面也会经常问到,在之前也多次了解过源码,今天算是复习一下,顺便好好总结一下,包括在后面有 相关面试题.本文不会对红黑树代码由太多深入研究,特别是删除方面太复杂, ...
- JDK1.8 的 HashMap 源码之文件注释
文章目录 null 插入,key的位置变化 迭代操作时间 性能因素 负载因子 Comparable 加锁 迭代器修改 null 插入,key的位置变化,迭代操作时间,性能因素,负载因子,Compara ...
- java并发:jdk1.8中ConcurrentHashMap源码浅析
ConcurrentHashMap是线程安全的.可以在多线程中对ConcurrentHashMap进行操作. 在jdk1.7中,使用的是锁分段技术Segment.数据结构是数组+链表. 对比jdk1. ...
- HashMap源码及原理
HashMap 简介 底层数据结构分析 JDK1.8之前 JDK1.8之后 HashMap源码分析 构造方法 put方法 get方法 resize方法 HashMap常用方法测试 感谢 changfu ...
- HashMap源码与相关面试题
一.哈希表 哈希表是一种可以快速定位得数据结构.哈希表可以做到平均查找.插入.删除时间是O(1),当然这是指不发生Hash碰撞得情况.而哈希表最大得缺陷就是哈希值得碰撞(collision). Has ...
- 详解HashMap源码解析(上)
jdk版本:1.8 数据结构: HashMap的底层主要基于数组+链表/红黑树实现,数组优点就是查询块,HashMap通过计算hash码获取到数组的下标来查询数据.同样也可以通过hash码得到数组下标 ...
- JDK1.8 HashMap源码分析
一.HashMap概述 在JDK1.8之前,HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的节点都存储在一个链表里.但是当位于一个桶中的元素较多,即hash值相等的元素较多时 ...
随机推荐
- Linux 文件查询
查看文件类型:file 如果你想要知道某个文件的基本数据,例如是属于ASCII或者是data文件,或者是binary,且其中有没有使用到动态函数库等等的信息,可以用file查看 which (寻找“执 ...
- Thingsboard Docker关闭后重启服务创建network出错
因为个人想验证一下thingsboard的数据是否是保存在postgres中,就将postgres容器停止,后想重启则无法重启 我干脆将整个系统删除后重新再来一次,在试的时候发现无法重新创建容器 Cr ...
- 深度学习面试题11:池化(same池化、valid池化、带深度的池化)
目录 Same最大值池化 多深度的same池化 Same平均值池化 Valid池化 参考资料 池化(Pooling)操作与卷积类似,取输入张量的每个位置的矩形领域内的最大值或平均值作为该位置的输出. ...
- DELPHI给整个项目加编译开关
DELPHI给整个项目加编译开关 project--options
- 去掉iframe周围的空白
今天,在处理一个网页样式时,遇到了一小问题,就是调用的iframe四周出现了空白. iframe调用的代码如下: 示例: <iframe src="http://www.xxx.c ...
- element-ui表格显示html格式
<el-table-column type="String" label="内容" prop="tpl" width="58 ...
- 一个java创建,删除,构建Jenkins等功能的JenkinsUtil工具类
package com.vip.webpagetest.utils; import java.io.InputStream;import java.util.ArrayList;import java ...
- 从内核3.7版本开始,Linux就开始支持VXLAN 到了内核3.12版本,Linux对VXLAN的支持已经完备,支持单播和组播,IPv4和IPv6。
一.关于VXLAN VXLAN 是 Virtual eXtensible LANs 的缩写,它是对 VLAN 的一个扩展,是非常新的一个 tunnel 技术,在Open vSwitch中应用也非常多. ...
- FrameLayout--霓虹灯
主函数里面,新建一个线程,控制改变背景色 package com.example.framelayout import android.support.v7.app.AppCompatActivity ...
- centos7安装python3.6独立的virtualenv环境
centos7安装python3.6独立的virtualenv环境 1.编译安装python3.6环境# 安装依赖yum -y install zlib-devel bzip2-devel opens ...