HashMap 和 HashSet 的预分配方法 - 一口 Java
Billy Korando 于 2022 年 10 月 24 日发布
自 JDK 1.2 以来,HashMap
和 HashSet
类一直是 JDK 的一部分;然而,在很长一段时间内,这些类及其子类一直存在使用模式不佳的问题。在本文中,我们将探讨开发人员在使用这些类时经常犯的错误、此错误的影响,以及 JDK 19 中添加到这些类中的新工厂方法如何解决此问题。我们来看看。
设置初始容量
HashMap
和 HashSet
类及其子类 LinkedHashMap
、LinkedHashSet
和 WeakHashMap
提供了可以设置“容量”值的构造函数。实际上,此值是映射或集合的内部表大小,它必须大于映射或集合预期的条目数。指定错误的值会导致在填充映射或集合时进行代价高昂的重新分配。
设置预分配的映射和集合
为了解决 JDK 19 中的此问题,静态工厂方法 new<TypeName>(int numMappings)
(例如 newHashMap(int numMappings)
)已添加到 HashMap
、HashSet
及其子类中。新的工厂方法将返回一个映射或集合,其容量基于 0.75
的默认负载工厂设置。此更改的结果是性能得到了一点但明显的提升,如下表所示
Method used: Elements: Execution time (avg):
Constructor 10 380.079 ns/op
Factory 10 378.929 ns/op
Constructor 100 4135.819 ns/op
Factory 100 3847.426 ns/op
Constructor 1000 39970.521 ns/op
Factory 1000 37568.595 ns/op
注意:请参阅其他阅读内容,了解用于获得上述结果的基准测试存储库的链接。性能测试困难且耗时,结果会因使用情况和系统架构而异。
使用预分配的映射和集合
当开发人员使用映射或集合时,可能不知道元素的数量。在这种情况下,使用预分配工厂方法的好处很小,或者可能导致内存使用过多。仅当您对预期的集合容量有很好的了解时,才应使用预分配工厂方法。
其他阅读内容
- HashMap Javadoc
- 需要创建预大小 HashMap 的方法
- 预分配基准测试
- OpenJDK:魔法发生的地方(介绍将预分配方法作为对 OpenJDK 做出贡献的一个示例的演示文稿)
编码愉快!