longtext长度为0是什么意思_为什么 HashMap 中链表长度大于 8 才转化为红黑树?

Java 中的 HashMap 采用链表法来解决哈希冲突(HashMap 原理),即具有相同桶下标的键值对使用一个链表储存。当链表变长时,查找和添加(需要确定 key 是否已经存在)都需要遍历这个链表,速度会变慢。JDK 1.8 后加入了链表转换为红黑树的机制,但是红黑树的转换并不是一个廉价的操作,只有当链表长度大于等于 TREEIFY_THRESHOLD 才会 treeify。

    /*** The bin count threshold for using a tree rather than list for a* bin.  Bins are converted to trees when adding an element to a* bin with at least this many nodes. The value must be greater* than 2 and should be at least 8 to mesh with assumptions in* tree removal about conversion back to plain bins upon* shrinkage.*/static final int TREEIFY_THRESHOLD = 8;

TREEIFY_THRESHOLD 默认为 8,putVal() 源码如下:

    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);

实际上并不是只要链表长度大于 8 就会 treeify。当 table.length(桶的个数)小于 MIN_TREEIFY_CAPACITY 时会优先扩容而不是转换为红黑树。

    /*** The smallest table capacity for which bins may be treeified.* (Otherwise the table is resized if too many nodes in a bin.)* Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts* between resizing and treeification thresholds.*/static final int MIN_TREEIFY_CAPACITY = 64;

MIN_TREEIFY_CAPACITY 默认为 64,treeifyBin() 源码大致是这样:

    final void treeifyBin(Node<K,V>[] tab, int hash) {int n, index; Node<K,V> e;if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) // 大小不够,优先扩容resize();else if ((e = tab[index = (n - 1) & hash]) != null) {// ...}}

为什么是 8 ?

TREEIFY_THRESHOLD 的默认值 8 是如何确定的呢?源码中的注解其实给出了答案:

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 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)). The first values are:

treeify 过程会把原本的 Node 对象转化为 TreeNode 对象,而 TreeNode 大小是 Node 的两倍;除去内存的损耗,treeify 本身也是一个耗时的过程,并且在红黑树节点数小于等于 UNTREEIFY_THRESHOLD(默认为 6)时,红黑树又会重新转换为链表,如果出现频繁的相互转化,这是一笔不小的开销。

所以我们需要确定一个 k 值,链表长度大于等于 k 时,会转化为红黑树。k 不能太大,因为链表的长度过大会影响插入和查找效率;k 也不能太小,treeify 并不是一个廉价的操作,我们希望链表长度大于等于 k 的概率要足够小,这样就可以尽量避免 treeify。

链表长度为 k 的概率就是出现 k 个键值对都在同一个桶中的概率,假设 table 的长度为 m,也就是有 m 个桶,一个键值对落入每一个桶都是等概率的,求不同 k 对应的概率就是标准的泊松分布问题:

equation?tex=P%28X%3Dk%29%3D%5Cfrac%7Be%5E%7B-%5Clambda%7D%5Clambda%5Ek%7D%7Bk%21%7D%5Ctag%7B1%7D

其中

equation?tex=%5Clambda%3Dnp , 由于等概率,所以
equation?tex=p%3D%5Cfrac%7B1%7D%7Bm%7D ,关键在于求
equation?tex=n,也就是键值对的个数。

通常情况下 HashMap 都是要经历扩容过程的,扩容后 table 的长度是原来的两倍,不妨以这个角度来考虑键值对的个数。我们知道当键值对个数大于等于加载因子(默认 0.75f)和当前 table 长度的乘积时,会发生扩容,所以刚刚完成扩容时:

equation?tex=n_%7B1%7D+%3D+0.75+%5Ctimes%5Cfrac%7Bm%7D%7B2%7D%5Ctag%7B2%7D

要发生下一次扩容时:

equation?tex=n_%7B2%7D%3D0.75%5Ctimes+m%5Ctag%7B3%7D

求均值:

equation?tex=n+%3D+%5Cfrac%7Bn_%7B1%7D+%2B+n_%7B2%7D%7D%7B2%7D%5Capprox0.5m%5Ctag%7B4%7D 最后求得:

equation?tex=%5Clambda%3Dnp%5Capprox0.5m%5Ctimes%5Cfrac%7B1%7D%7Bm%7D%3D0.5%5Ctag%7B5%7D

带入式(1),得出下表:

  • X = 0: P = 0.60653066
  • X = 1: P = 0.30326533
  • X = 2: P = 0.07581633
  • X = 3: P = 0.01263606
  • X = 4: P = 0.00157952
  • X = 5: P = 0.00015795
  • X = 6: P = 0.00001316
  • X = 7: P = 0.00000094
  • X = 8: P = 0.00000006
  • X > 8: P less than 1 in ten million

可以看到 8 个键值对同时存在于同一个桶的概率只有 0.00000006,比 8 大的概率更是小于千万分之一,就它了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356505.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ulink2 No Ulink Device found 解决办法

一、背景keil使用ULINK2调试的时候&#xff0c;提示"No Ulink Device found"&#xff0c;"error: flash download failed - Target DLL has cancelled" 。之前一直都OK&#xff0c;然后今天突然不行&#xff0c;插上的时候&#xff0c;"COM",&qu…

python图形界面教程_图形教程

python图形界面教程众所周知&#xff0c;我们可以借助Java库制作游戏&#xff0c;这些库为我们提供制作游戏所需的图形。 因此&#xff0c;今天我将开始一个关于Java图形的非常新的部分。 我之前曾发表过有关如何制作所得税计算器的文章 。 首先要满足一些先决条件&#xff1a;…

java创建树结构_Java学习之XML-017

如果想快速有效的学习&#xff0c;思想核心是“以建立知识体系为核心”&#xff0c;具体方法是“守破离”。反复练习直到熟练。————百战程序员1.0 XML1.1 XML 简介XML 指可扩展标记语言。XML 被设计用来传输和存储数据。1. 什么是XMLXML 指可扩展标记语言&#xff08;EXten…

dll文件是什么

dll实际上是动态链接库的缩写&#xff0c;从windows1.0开始&#xff0c;动态链接库就是整个操作系统的基础&#xff0c;那么这有什么作用呢&#xff1f;在dos时代&#xff0c;程序员是通过编写程序来达到预期的目的的&#xff0c;每实现一个目的就需要编写一个程序&#xff0c;…

minecraft pythonapl_Substance PythonAPI入门案例

第一次在知乎发文&#xff0c;技术朋友们请多包涵。Substance Designer自去年夏天2018版推出Python API至今已有一年&#xff0c;从一开始的寒酸到现在的初成规模&#xff0c;官方的API库也随着版本的更新不断完善。目前网上(包括youtube)相关的教程甚少&#xff0c;即便是官方…

创建示例HTTPS服务器以获取乐趣和收益

通常&#xff0c;在开发人员或/和针对实际场景进行测试期间&#xff0c;我们&#xff08;开发人员&#xff09;面临着运行成熟的HTTPS服务器的需求&#xff0c;可能同时进行一些模拟。 在JVM平台上&#xff0c;除非您知道适合此工作的正确工具&#xff0c;否则它过去并不是一件…

WebDriver API元素的定位

一、以下截图为用FireBug定位的用火狐(Firefox)浏览器打开的百度首页&#xff0c;下面所讲述的八种定位方法&#xff0c;就是以该截图中的百度输入框为例子。 ①、FireBug是Firefox浏览器下的开发类插件&#xff0c;通过该插件可以查看HTML、CSS、Javascript控制台、网络状况监…

mysql字符乱码百度_如何解决MySQL字符集乱码问题

变量 a 的字符编码是由参数 CHARACTER_SET_CLIENT 决定的&#xff0c;假设此时编码为 A&#xff0c;也就是变量 a 的编码。2. 写入语句在发送到 MySQL 服务端之前的编码由 CHARACTER_SET_CONNECTION 决定&#xff0c;假设此时编码为 B。3. 经过 MySQL 一系列词法&#xff0c;语…

[水煮 ASP.NET Web API2 方法论](1-6)Model Validation

问题 想要 ASP.NET Web API 执行模型验证&#xff0c;同时可以和 ASP.NET MVC 共享一些验证逻辑。 解决方案 ASP.NET Web API 与 ASP.NET MVC 支持一样的验证机制&#xff0c;都是通过System.ComponentModel.DataAnnoataions 的属性验证。使用框架提供的相关验证属性&#xff0…

findbugs-dea_FindBugs和JSR-305

findbugs-dea假设该组开发人员在大型项目的各个部分上并行工作-一些开发人员在进行服务实现&#xff0c;而其他开发人员在使用该服务的代码。 考虑到API的假设&#xff0c;两个小组都同意服务API&#xff0c;并开始单独工作。 您认为这个故事会有幸福的结局吗&#xff1f; 好吧…

课程2 谈论音乐行业的趋势

1. 音乐词汇 CDdownloadLPsrecordsvinyl 黑胶sounddlbum covers 专辑封面2. 使用类似单词谈论各种录制你和聆听音乐的不同媒体 I still prefer the sound of my old LP records.My father used to by a lot of CDs.Most of my music these days is MP3s.3. 你可以使用这些词来谈…

带有ActiveMQ和Maven的JMS Sender应用程序

我们已经看到了如何使用ActiveMQ和Maven创建JMS Receiver应用程序 。 让我们看看我们如何类似地创建JMS Sender应用程序 。 web.xml与创建接收器应用程序时使用的相同&#xff1a; <web-app xmlns"http://java.sun.com/xml/ns/javaee"xmlns:xsi"http://www…

mysql自连接查询的sql语句_mysql 自连接

SELECT语句中的自连接。到目前为止&#xff0c;我们连接的都是两张不同的表&#xff0c;那么能不能对一张表进行自我连接呢&#xff1f;答案是肯定的。有没有必要对一张表进行自我连接呢&#xff1f;答案也是肯定的。表的别名&#xff1a;一张表可以自我连接。进行自连接时我们…

Spring的Lifecycle

Lifecycle接口定义了每个对象的重要方法&#xff0c;每个对象都有自己的生命周期需求&#xff0c;如下&#xff1a; public interface Lifecycle { void start(); void stop(); boolean isRunning(); } 任何spring管理的对象都可以实现这个接口。那么&#xff0c;当Appl…

mysql aes密钥大于16位_aes秘钥限制问题解决办法

在oarcle jdk1.8上执行256位的aes秘钥加密报错如下:java.lang.RuntimeException: java.security.InvalidKeyException: Illegal key sizeat com.xx.opal.core.utils.aes.AESTool.encryptWithoutEncode(AESTool.java:33)at com.xx.opal.aes.AESTest.test(AESTest.java:19)at sun…

background-clip与background-origin

规定背景的绘制区域 浏览器支持 IE9、Firefox、Opera、Chrome 以及 Safari 支持 background-clip 属性。 注释&#xff1a;Internet Explorer 8 以及更早的版本不支持 background-clip 属性。IE9、Firefox、Opera、Chrome 以及 Safari 支持 background-clip 属性。 有三个值&am…

策略模式应用场景和uml_策略模式

策略模式应用场景和uml在最近的博客中&#xff0c;我收到了Wojciech Soczy&#xff1f;ski的评论&#xff0c;内容涉及在使用“不要问”&#xff08;TDA&#xff09;时如何使用“战略”模式实施单一责任原则&#xff08;SRP&#xff09;。 在某些时候&#xff0c;我打算进一步讨…

mysql建表时主键_mysql建表时怎么设置主键?

设置方法&#xff1a;在“CREATE TABLE”语句中&#xff0c;通过“PRIMARY KEY”关键字来指定主键&#xff0c;语法格式“字段名 数据类型 PRIMARY KEY [默认值]”或“[CONSTRAINT 约束名] PRIMARY KEY 字段名”。主键(PRIMARY KEY)的完整称呼是“主键约束”&#xff0c;是 MyS…

mysql的考试范围_数据库考试范围整理

填空&#xff1a;1.目前常用的数据库管理系统软件有Access 、SQL Sever和Oracle.2.数据实际上就是存储在某一种媒体上的能够被识别的物理符号。3.一个关系的逻辑结构就是一个二维表。4.对关系进行选择、投影或连接运算之后&#xff0c;运算的结果仍然是一个关系。5.在关系数据库…

Java EE 8 MVC:控制器的详细介绍

Java EE MVC是为Java EE 8规划并在JSR-371中指定的基于动作的新MVC框架。 这是我的Java EE 8 MVC教程的第二篇文章。 第一篇文章介绍了基础知识&#xff0c;并展示了如何开始使用 Java EE 8 MVC参考实现Ozark 。 在本文中&#xff0c;我们将更详细地介绍MVC控制器。 MVC控制器…