我需要知道Java放大的地图何时。为此,我需要一个公式来计算良好的初始容量。
在我的项目中,我需要一个包含大对象的大型地图。因此,我想通过指定合适的初始容量来防止调整地图的大小。通过反思,我研究了地图的行为。
package com.company;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map m = new HashMap();
int lastCapacity = 0, currentCapacity = 0;
for (int i = 1; i <= 100_000; i++) {
m.put(i,i);
currentCapacity = getHashMapCapacity(m);
if (currentCapacity>lastCapacity){
System.out.println(lastCapacity+" --> "+currentCapacity+" at "+i+" entries.");
lastCapacity=currentCapacity;
}
}
}
public static int getHashMapCapacity(Map m){
int size=0;
Field tableField = null;
try {
tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(m);
size = table == null ? 0 : table.length;
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return size;
}
}
输出为:
0->在1个条目中16。
16-> 32个条目。
32->在25个条目时64。
64-> 128在49个条目中。
128-> 256在97条目中。
256-> 512在193个条目。
512-> 1024在385条目中。
1024-> 2048在769条目。
2048-> 4096在1537条目。
4096-> 8192在3073条目。
8192-> 16384在6145条目。
16384-> 32768在12289条目。
32768-> 65536在24577条目中。
65536-> 131072在49153条目。
131072-> 262144在98305条目。
我可以假设地图总是以这种方式行为?Java 7和Java 8之间有任何区别吗?
查看这种行为的最简单方法是查看OpenJDK源。它们都是免费的,相对易于阅读。
在这种情况下,检查hashmap,您会看到一些广泛的实施说明可以解释尺寸的工作方式,将载荷因子用作阈值(这是您所看到的行为(,甚至决定的决定是如何的制作是否将树木用于垃圾箱。通读,如果不清楚,请回来。
通过扩展非常便宜的操作,该代码非常优化。我建议使用个人资料来获得一些证据,表明在进行任何调整之前,性能问题与扩展有关。
根据文档:
在设置其初始容量时,应考虑地图中预期的条目及其负载因子,以最大程度地减少重新操作的数量。如果初始容量大于最大条目数除以负载因子,则不会发生重新操作。https://docs.oracle.com/javase/8/docs/api/java/java/util/hashmap.html