public static void longLongAGo() {
int count = 1000000;
System.out.println("---------------- 不设置hashMap初始容量 ------------");
long start = System.currentTimeMillis();
HashMap<Integer, Object> map = new HashMap<>();
for (int i = 0; i < count; i++) {
map.put(i, UUID.randomUUID());
}
long end = System.currentTimeMillis();
System.out.println("添加1000000个元素耗时:" + (end - start));
System.out.println("---------------- 设置hashMap初始容量 -------------------");
long start1 = System.currentTimeMillis();
HashMap<Integer, Object> map1 = new HashMap<>(count);
for (int i = 0; i < count; i++) {
map1.put(i, UUID.randomUUID());
}
long end1 = System.currentTimeMillis();
System.out.println("添加1000000个元素耗时:" + (end1 - start1));
}
在初始化的时候设定了map的容量,不会在添加元素的过程中进行自动扩容了,大大提高了性能,从结果看确实如此!所以,集合初始化时,指定集合初始值大小能提升性能。
当设置初始容量为1000000时,容器并不是想象中的不扩容了,而是也扩容了1次:
public static void longLongAGo() throws Exception {
int count = 1000000;
System.out.println("---------------- 初始化hashMap容量为1000000 ------------");
int resizeCount = 0;
HashMap<Integer, Object> map = new HashMap<>(count);
Method capacityMethod = map.getClass().getDeclaredMethod("capacity");
capacityMethod.setAccessible(true);
int capacity = (int) capacityMethod.invoke(map);
System.out.println("初始容量:" + capacity);
for (int i = 0; i < count; i++) {
map.put(i, UUID.randomUUID());
int curCapacity = (int) capacityMethod.invoke(map);
if (curCapacity > capacity) {
System.out.println("当前容量:" + curCapacity);
resizeCount++;
capacity = curCapacity;
}
}
System.out.println("hashMap扩容次数:" + resizeCount);
}
/**
* Returns a power of two size for the given target capacity.
*/
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
细想下扩容原理即可知道
完美的方式之一可以用:
Maps.newHashMapWithExpectedSize(list.size())
源码:
/**
* Returns a capacity that is sufficient to keep the map from being resized as
* long as it grows no larger than expectedSize and the load factor is >= its
* default (0.75).
*/
static int capacity(int expectedSize) {
if (expectedSize < 3) {
checkNonnegative(expectedSize, "expectedSize");
return expectedSize + 1;
}
if (expectedSize < Ints.MAX_POWER_OF_TWO) {
return expectedSize + expectedSize / 3;
}
return Integer.MAX_VALUE; // any large value
}
Maps.newHashMapWithExpectedSize(list.size())