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值相等的元素较多时 ...
随机推荐
- [CMS]Joomla 3.4.6-RCE漏洞复现
0x00:简介 1.Joomla是一套全球有名的CMS系统. 2.Joomla基于PHP语言加上MySQL数据库所开发出来的WEB软件系统,目前最新版本是3.9.12. 3.Joomla可以在多种不同 ...
- linux10.日志服务器建立和克隆机的网卡问题
日志服务器建立 克隆虚拟机网卡混乱问题处理 vim /etc/udev/rules.d/70-perisistent-net.rules 调整mac地址与设备的对应关系 ...
- cropper.js移动端使用
cropper.js移动端使用 一.总结 一句话总结: 启示:找对关键词,找对相关方面的应用,效果真的非常好 比如 cropper.js移动端使用,这样设置了(dragMode: 'move',//拖 ...
- Django,Flask,Tornado三大框架对比,Python几种主流框架,13个Python web框架比较,2018年Python web五大主流框架
Django 与 Tornado 各自的优缺点Django优点: 大和全(重量级框架)自带orm,template,view 需要的功能也可以去找第三方的app注重高效开发全自动化的管理后台(只需要使 ...
- input type color
<input type="color"> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input ...
- sysfs 控制gpio
按照下面的命令点亮及熄灭LED pi@raspberrypi:/sys/class/gpio $echo 26 > exportpi@raspberrypi:/sys/class/gpio $ ...
- 部署gerrit环境完整记录【转】
开发同事提议在线上部署一套gerrit代码审核环境,废话不多说,部署gerrit的操作记录如下:提前安装好java环境,mysql环境,nginx环境测试系统:centos6.5下载下面三个包,放到/ ...
- sass - &的作用
6.8. & in SassScript 就像在选择器中使用时一样,&在SassScript中引用当前父选择器.它是一个逗号分隔的列表和空格分隔的列表.例如: .foo.bar .ba ...
- docker容器日志查看
日志分两类,一类是 Docker 引擎日志:另一类是 容器日志. Docker 引擎日志 Docker 引擎日志 一般是交给了 Upstart(Ubuntu 14.04) 或者 systemd (Ce ...
- 【MySQL】Mac通过brew安装的MySQL重启方法
问题 在 Mac 上通过 brew install mysql 安装的的MySQL使用基本MySQL命令重启会失败: mysql.server stop mysql.server start mysq ...