new HashMap(int) 和 guava Maps.newHashMapWithExpectedSize(int) 的区别

问题描述 投票:0回答:3

在 Java 中,您可以创建一个新的

HashMap
来保存特定数量的项目,如下所示:

Map m = new HashMap(100);

Guava 提供了一个

Maps.newHashMapWithExpectedSize(int)
方法,我希望它可以简单地调用
HashMap(int)
。但它并没有这样做,而是计算自己的容量并使用它。

为什么

newHashMapWithExpectedSize
做自己的事情,为什么我要使用它而不是直接调用
new HashMap(int)

java collections guava
3个回答
12
投票

你读过方法的Javadoc了吗?

创建一个

HashMap
实例,具有足够高的“初始容量”,它应该容纳
expectedSize
元素而不增长。

请注意,

new HashMap(int)
构造函数的“初始大小”参数指定存储条目的哈希表 的初始大小,这基本上是您不必关心的实现细节。当哈希表超过地图的 load factor(默认为 0.75)时,它会调整大小,这意味着如果您指定初始容量为 16,然后向地图添加 16 个条目,则哈希表几乎肯定会调整大小。

使用 Guava 的方法,如果您指定 expected size 为 16,然后添加 16 个条目,哈希表应该 not 调整大小。


3
投票

HashMap 的构造函数参数是映射的容量,即桶的数量。

因此,如果您将 10 作为参数传递,并在映射中存储 8 个键,将达到重新哈希阈值(默认为 75%)并且地图将重新哈希。

另一方面,传递给 newHashMapWithExpectedSize() 的参数是地图的预期大小。因此,如果您传递 10,Guava 将创建一个具有足够桶的地图,以确保在插入 10 个元素时地图不会重新散列:至少 14 个桶。


0
投票

Guava 只是将传递的大小乘以 2(以安全的方式)并调用常规的 hashmap 构造函数。这使得它更稀疏,因此散列时冲突更少。

关于容量计算的 javadoc 提到它计算容量值,使 hashmap 充满 25% 到 50%,这远离会触发调整大小的阈值。

标准库将预期大小四舍五入为最接近的 2 的幂并将其分配为大小,然后将调整大小的阈值设置为 75%。如果我们随机询问大小,标准库会在 50% 的情况下调整大小。

如果避免阈值是唯一的考虑因素,乘以 1.34 就足以有足够的空间来避免在用预期的元素大小填充它时调整大小。

这看起来像是典型的速度与空间的权衡,谷歌的工程师更喜欢速度,而 Sun/Oracle 的工程师更喜欢太空。

© www.soinside.com 2019 - 2024. All rights reserved.