以ArrayList爲例,對比下指定初始容量和不指定兩種情況對List.add性能的影響
/**
* 指定初始容量後:耗時 1030
*/
ArrayList<Object> list = new ArrayList<Object>();
final int N = 10000000;
list = new ArrayList<Object>(N);
long startTime1 = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
list.add(i);
}
long endTime1 = System.currentTimeMillis();
System.out.println("指定初始容量後:" + (endTime1 - startTime1));
/**
* 不指定容量:耗時 1432
*/
ArrayList<Object> list = new ArrayList<Object>();
final int N = 10000000;
list = new ArrayList<Object>();
long startTime1 = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
list.add(i);
}
long endTime1 = System.currentTimeMillis();
System.out.println("不指定容量:" + (endTime1 - startTime1));
指定容量的List做add操作明顯比不指定的快。
ensureCapacity方法
如果List的初始化不是自己掌握的,那麼我們在add大量數據之前可以調用 list.ensureCapacity(N); 以減少增量重新分配的次數,提升List的add性能。
ArrayList.ensureCapacity 源碼如下:
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
下面進行ensureCapacity測試
/**
* 不使用 ensureCapacity耗時 1916
*/
ArrayList<Object> list = new ArrayList<Object>();
final int N = 10000000;
long startTime = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
list.add(i);
}
long endTime = System.currentTimeMillis();
System.out.println("不使用ensureCapacity:"+(endTime - startTime));
/**
* 使用 ensureCapacity 耗時 1089
*/
ArrayList<Object> list = new ArrayList<Object>();
final int N = 10000000;
list = new ArrayList<Object>();
long startTime1 = System.currentTimeMillis();
list.ensureCapacity(N);
for (int i = 0; i < N; i++) {
list.add(i);
}
long endTime1 = System.currentTimeMillis();
System.out.println("使用ensureCapacity方法後:" + (endTime1 - startTime1));
答案顯而易見
何況,阿里手冊上也有相關信息:
【推薦】集合初始化時,指定集合初始值大小。
說明:HashMap 使用 HashMap(int initialCapacity) 初始化。
正例:initialCapacity = (需要存儲的元素個數 / 負載因子) + 1。注意負載因子(即 loader factor)默認
爲 0.75,如果暫時無法確定初始值大小,請設置爲 16(即默認值)。
反例:HashMap 需要放置 1024 個元素,由於沒有設置容量初始大小,隨着元素不斷增加,容量 7 次被
迫擴大,resize 需要重建 hash 表,嚴重影響性能。