前言:
ArrayList的扩容问的挺多的,但是在ArrayList中还有一个几乎容易忽略的方法trimToSize,下面就用几个简单的方法验证一下。
/**
* @program
* @description:
* @author: xiao
* @create: 2020/5/15 12:05 AM
**/
public class ArrayListTrimDemo {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
ArrayList<Integer> list = new ArrayList<>();
Class clazz = list.getClass();
//ArrayList内部维护的数组
Field field =clazz.getDeclaredField("elementData");
field.setAccessible(true);
Object obj ;
printArrayListRealSize(list, field, "第一次初始化列表实际长度:");
for (int i = 0; i < 100; i++) {
if (i == 0){
list.add(i);
//初始化是10
printArrayListRealSize(list, field, "第一次添加元素时列表实际长度:");
continue;
}
//然后又添加了99个元素
list.add(i);
}
//所以,这里是99+10 = 109
printArrayListRealSize(list, field, "第二次添加列表实际长度:");
//移除所有的元素
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
Integer next = iterator.next();
iterator.remove();
}
// list.clear();
printArrayListRealSize(list, field, "使用迭代器移除所有的元素后列表实际长度:");
System.out.println("经过「移除」后list的值:"+ Arrays.toString(list.toArray()));
//使用arrayList特有的"缩容"方法
list.trimToSize();
printArrayListRealSize(list, field, "使用trimToSize后列表实际长度:");
}
private static void printArrayListRealSize(ArrayList<Integer> list, Field field, String info) throws IllegalAccessException {
Object obj = field.get(list);
System.out.println(info + Array.getLength(obj));
}
}
最后结果:
第一次初始化列表长度:0
第一次添加元素时列表长度:10
第二次添加列表长度:109
使用迭代器移除所有的列表长度:109
使用remove移除所有的列表长度:109
经过两轮的「移除」后list的值:[]
使用remove移除所有的列表长度:0
再贴出源码:
/**
* Trims the capacity of this <tt>ArrayList</tt> instance to be the
* list's current size. An application can use this operation to minimize
* the storage of an <tt>ArrayList</tt> instance.
*/
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
最后由此可以得出结论,「缩容」是可以有效减少ArrayList实际占用。
参考: