在Java中,您可以像这样创建一个新的HashMap
来保存特定数量的项:
Map m = new HashMap(100);
Guava 提供了一个 Maps.newHashMapWithExpectedSize(int)
方法,我本以为它只会调用 HashMap(int)
。但实际上并非如此,它会计算自己的容量并使用。
为什么 newHashMapWithExpectedSize
会这样做,我该何时使用它而不是直接调用 new HashMap(int)
呢?
在Java中,您可以像这样创建一个新的HashMap
来保存特定数量的项:
Map m = new HashMap(100);
Guava 提供了一个 Maps.newHashMapWithExpectedSize(int)
方法,我本以为它只会调用 HashMap(int)
。但实际上并非如此,它会计算自己的容量并使用。
为什么 newHashMapWithExpectedSize
会这样做,我该何时使用它而不是直接调用 new HashMap(int)
呢?
你读过这个方法的Javadoc吗?
创建一个
HashMap
实例,初始容量足够大,可以在不扩容的情况下容纳expectedSize
个元素。
请注意,new HashMap(int)
构造函数的“初始大小”参数指定了存储条目的哈希表的初始大小,这基本上是您不必关心的实现细节。当哈希表超过地图的负载因子(默认为0.75)时,哈希表将调整大小,这意味着如果您指定了16的初始容量,然后向地图添加16个条目,则哈希表几乎肯定会被调整大小。
使用Guava的方法,如果您指定了16的预期大小,然后添加16个条目,则哈希表不应该调整大小。
HashMap构造函数的参数是map的容量,即桶的数量。
因此,如果将10作为参数传递,并在map中存储8个键,则会达到再散列阈值(默认为75%),并且map将重新散列。
另一方面,传递给newHashMapWithExpectedSize()的参数是map的预期大小。因此,如果传递了10,则Guava将创建一个具有足够桶的映射,以确保在插入10个元素时不会重新散列:至少14个桶。
HashMap
使用下一个二次幂作为其容量。因此,如果您将 initialCapacity
设置为 10,则实际容量将为 16。通过将其乘以 0.75,可以得到不调整大小的总共 12 个条目。 - BubletaninitialCapacity
值,表格将必须调整大小和重新散列以添加那么多条目的事实。 - ColinDnew HashMap(n)
然后放入 n 个条目,哈希表会因为 JDK 的定义不够大而被重新调整大小;Guava 只是在补偿这一点。 - Louis WassermanMap
,哈希表最终的大小都会差不多,因此不应该有任何显著的空间差异。唯一的区别在于在添加所有要添加的条目之前是否必须调整哈希表的大小。 - ColinD
HashMap
的大小以容纳特定数量的项。相反,它将其大小调整为指定数量的75%。 - ColinD