HashMap有两个重要的属性:size和load factor.我浏览了Java文档,它说的0.75f是初始加载因子.但我找不到它的实际用途.
有人可以描述我们需要设置负载因子的不同场景以及针对不同情况的一些样本理想值吗?
我试图找出特定情况下的最佳容量和负载系数.我想我已经掌握了它的要点,但我还是要感谢那些比我更了解的人的确认.:)
如果我知道我的HashMap将填充包含100个对象,并且大部分时间都会花费100个对象,我猜测最佳值是初始容量100和加载因子1?或者我需要容量101,还是有其他问题?
编辑:好的,我留出几个小时做了一些测试.结果如下:
EDIT2:我也添加了一些图表.这是说明加载因子0.75和1之间的差异的一个,在我初始化HashMap并将其填充到满容量的情况下.在y标度上是以ms为单位的时间(越低越好),x标度是大小(对象的数量).由于尺寸线性变化,所需时间也呈线性增长.
所以,让我们看看我得到了什么.以下两个图表显示了负载系数的差异.第一张图表显示了当HashMap填满容量时会发生什么; 由于调整大小,负载系数0.75表现更差.然而,它并不总是更糟糕,并且有各种各样的颠簸和跳跃 - 我想GC在这方面有重大影响.载荷系数1.25与1相同,因此它不包含在图表中.

该图表证明由于调整大小,0.75更差; 如果我们将HashMap填充到一半容量,0.75并不差,只是......不同(它应该使用更少的内存并且具有不可思议的更好的迭代性能).

还有一件事我想表现出来.这可以获得所有三个加载因子和不同HashMap大小的性能.除了加载因子1的一个峰值之外,一直保持不变.我真的想知道那是什么(可能是GC,但谁知道).

以下是感兴趣的人的代码:
import java.util.HashMap;
import java.util.Map;
public class HashMapTest {
// capacity - numbers high as 10000000 require -mx1536m -ms1536m JVM parameters
public static final int CAPACITY = 10000000;
public static final int ITERATIONS = 10000;
// set to false to print put performance, or to true to print get performance
boolean doIterations = false;
private Map<Integer, String> cache;
public void …Run Code Online (Sandbox Code Playgroud) 如果我有100个项目存储在字典中,我应该如此初始化它吗?
var myDictionary = new Dictionary<Key, Value>(100);
Run Code Online (Sandbox Code Playgroud)
我的理解是.NET字典在达到给定加载时在内部自行调整大小,并且加载阈值被定义为容量的比率.
这表明如果在上面的字典中添加了100个项目,那么当添加其中一个项目时它会自行调整大小.调整字典大小是我想要避免的,因为它会影响性能并浪费内存.
散列碰撞的概率与字典中的加载成比例.因此,即使字典没有自己调整大小(并使用其所有插槽),性能也必须因这些冲突而降低.
假设您知道字典中有多少项,那么应该如何最好地决定将字典初始化的能力?
在Java中,我有:
Set<Integer> set = new HashSet<Integer>();
callVoidMethod(set);
...
public static void callVoidMethod(Set<Integer> set) {
Set<Integer> superset = new HashSet<Integer>(set);
...
// I just added this loop to show that I'm adding quite a lot
// well, it depends on conditions, sometimes I add nothing,
// but it is unpredictable and do not know if add something
for (int i = 0; i < 1000; i++) {
...
if (conditionSatisfied) superset.add(someValue);
...
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码是简化的,想法是通过引用将集合传递给void方法并创建集合的完整副本,以便我们能够向副本添加一些新元素(这里是超集)并且不要触摸设置为我们在退出void方法时不需要它.
我的代码适用于大量数据处理,如果没有更快的方法来制作副本,那么我想优化HashSet自身,例如我不需要Integers作为键,但更好的原始int …
hashmap ×3
java ×3
.net ×1
capacity ×1
dictionary ×1
hash ×1
hashset ×1
integer ×1
load-factor ×1