标签:buffer ldd int span vat lap ide arraylist 对象
首先,ArrayList定义只定义类两个私有属性:
/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. */ private transient Object[] elementData; /** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size;
可知:elementData存储ArrayList内的元素,size表示它包含的元素的数量(不是指容量)。
注意:elementData用transient修饰,这表明当持久化ArrayList对象时,并不会保存它。
ArrayList是基于数组实现的,添加元素时,将某个位置的值设置为指定元素即可,但数组容量不够,如何扩容呢?
我们提供具体的方法来分析:
add方法:
// 将指定的元素添加到此列表的尾部。 public boolean add(E e) { ensureCapacity(size + 1); //判断容量是否足够,不够就扩容 elementData[size++] = e; return true; }
那么扩容的核心在于ensureCapacity方法
ensureCapacity方法:
public void ensureCapacity(int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { //size+1即添加后的长度,判断如果添加,会不会过长 Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; //1.5倍扩容 if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); //将老数组拷贝一份到新数组 } }
可知:
1. 每次添加前都会判断是否会过长,会,则先扩容
2. 每次扩容都是1.5倍扩容,其实是1.5倍+1。
3. 老数组通过Arrays.copyOf()拷贝一份到新数组
那么问题来了,每次扩容都是1.5倍是否会造成较大的空间浪费?
是的,所以建议在构造ArrayList实例时,就预估大小并指定其容量,以避免数组扩容的发生。或者根据实际需求,直接调用ensureCapacity方法来手动增加ArrayList实例的容量。
标签:buffer ldd int span vat lap ide arraylist 对象
原文地址:https://www.cnblogs.com/yanze/p/10083898.html