JEP 180:处理频繁的 HashMap 与平衡树的冲突
概括
java.util.HashMap
通过使用平衡树而不是链表来存储映射条目,提高在高哈希冲突条件下的性能。在班级中实施同样的改进LinkedHashMap
。
动机
JDK 8 中该领域的早期工作,即替代字符串哈希实现,仅改进了字符串值键的冲突性能,但这样做的代价是向每个String
实例添加新的(私有)字段。
此处提出的更改将提高任何实现Comparable
.然后可以删除替代的字符串散列机制,包括hash32
添加到类中的私有字段。String
描述
其主要思想是,一旦哈希桶中的项目数量超过某个阈值,该桶就会从使用条目链表切换到使用平衡树。在哈希冲突较高的情况下,这会将最坏情况下的性能从 O(n) 提高到 O(log n)。
该技术已在该类的最新版本中实现java.util.concurrent.ConcurrentHashMap
,该类也计划作为JEP 155的一部分包含在 JDK 8 中。该代码的部分内容将被重新用于在HashMap
和LinkedHashMap
类中实现相同的想法。仅实现会发生变化;不会修改任何接口或规格。一些用户可见的行为(例如迭代顺序)将在其当前规范的范围内发生变化。
我们不会在遗留Hashtable
类中实现此技术。自 Java 1.0 以来,该类一直是平台的一部分,并且已知一些使用它的遗留代码依赖于迭代顺序。Hashtable
将恢复到引入替代字符串哈希实现之前的状态,并将保持其历史迭代顺序。
我们也不会在 WeakHashMap 中实现这种技术。我们进行了尝试,但必须考虑弱密钥的复杂性导致微基准性能下降得令人无法接受。WeakHashMap
也将恢复到之前的状态。
无需在IdentityHashMap
课堂上实现此技术。它用于System.identityHashCode()
生成哈希码,因此冲突通常很少见。
测试
- 从 Doug Lea 的 JSR 166 CVS 工作区运行
Map
测试(包括几个微基准) - 运行标准工作负载的性能测试
- 可能开发新的微基准
风险和假设
这一变化将为平衡树的添加和管理引入一些开销;我们预计这一开销可以忽略不计。
此更改可能会导致类的迭代顺序发生更改HashMap
。该HashMap
规范明确不保证迭代顺序。类的迭代顺序LinkedHashMap
将保持不变。