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值相等的元素较多时 ...
随机推荐
- js中的那些遍历
说到遍历,首先想到的是数组的遍历,方法不要太多,比如 for, forEach,map,filter,every,some等 下面来看下,用法 首先 定义一个数组: 1. for循环,需要知道数组的长 ...
- SET NOCOUNT 的用法
SET NOCOUNT 使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息. 语法 SET NOCOUNT { ON | OFF } 注释 当 SET NOCOUNT ...
- T-MAX组--项目冲刺(第三天)
THE THIRD DAY 项目相关 作业相关 具体描述 所属班级 2019秋福大软件工程实践Z班 作业要求 团队作业第五次-项目冲刺 作业正文 T-MAX组--项目冲刺(第三天) 团队名称 T-MA ...
- vue 遇到防盗链 img显示不出来
在index.html中添加: <meta name="referrer" content="no-referrer">
- [转] FileZilla Server超详细配置
FileZilla Server下载安装完成后,必须启动软件进行设置,由于此软件是英文,本来就是一款陌生的软件,再加上英文(注:本站提供中文版本,请点击下载),配置难度可想而知,站长从网上找到一篇非常 ...
- [Linux] 60s快速分析Linux性能
转载: https://www.cnblogs.com/zichuan/p/10440617.html 之前在地铁上看到过一篇快速分析Linux系统性能的文章,觉得以后有用,今天就找了一下,转载过来. ...
- 性能分析 函数粒度 函数里的一条语句 汇编 反编译 机器指令 %rbx,%rbp
在Linux下做性能分析3:perf - 知乎 https://zhuanlan.zhihu.com/p/22194920 Linux Perf 性能分析工具及火焰图浅析 - 知乎 https://z ...
- flutter 中的搜索条实现
import 'package:flutter/material.dart'; import 'package:flutter_app/SearchBarDemo.dart'; void main() ...
- ISO/IEC 9899:2011 条款6.7.7——类型名
6.7.7 类型名 语法 1.type-name: specifier-qualifier-list abstract-declaratoropt abstract-declarator: po ...
- 记一次腾讯云MySQL数据库数据回滚
如题,因为操作人员的问题,需要对数据库数据进行回滚. 可以看到,设置了7天自动备份,且是物理冷备. 什么是物理冷备?科普一下: (1)热备:在数据库运行时,直接进行备份,对运行的数据库没有影响.(2) ...