ArrayList的扩容机制
1、案例1
public class Demo1 { public static void main(String[] args) throws Exception { // Vector空参构造:容量为10 Vector<Integer> vector = new Vector<>(); System.out.println("vector.capacity(): " + vector.capacity()); // 10 System.out.println("=== 分割线 ==="); ArrayList<Integer> list = new ArrayList<>(); System.out.println("list元素个数: " + list.size()); // 0 System.out.println("list的容量: " + getCapacity(list)); // 0 // 手动设置list集合的容量,因为9<DEFAULT_CAPACITY,所以不扩容 list.ensureCapacity(9); System.out.println("list元素个数: " + list.size()); // 0 System.out.println("list的容量: " + getCapacity(list)); // 0 // 手动设置list集合的容量,因为11>DEFAULT_CAPACITY,所以扩容 list.ensureCapacity(11); System.out.println("list元素个数: " + list.size()); // 0 System.out.println("list的容量: " + getCapacity(list)); // 11 } // 使用反射获取ArrayList集合的私有字段elementData, // elementData是一个Object数组,是ArrayList的底层实现;elementData数组的长度即为集合的容量 public static Integer getCapacity(ArrayList<?> list) throws Exception { Field field; field = list.getClass().getDeclaredField("elementData"); field.setAccessible(true); Object[] objArray = (Object[]) field.get(list); return objArray.length; } }
2、案例2
1)调用ArrayList空参构造创建集合,此时集合容量为0;
2)添加第1个元素后,集合容量扩为10;
3)当添加第11个后,集合容量扩为15(容量扩充为原来的1.5倍);
public class Demo2 { public static void main(String[] args) throws Exception { // Vector空参构造:容量为10 Vector<Integer> vector = new Vector<>(); System.out.println("vector.capacity(): " + vector.capacity()); // 10 System.out.println("=== 分割线 ==="); ArrayList<Integer> list = new ArrayList<>(); System.out.println("list元素个数: " + list.size()); // 0 System.out.println("list的容量: " + getCapacity(list)); // 0 list.add(0); // 第一次添加,list集合扩容至10 System.out.println("list元素个数: " + list.size()); // 1 System.out.println("list的容量: " + getCapacity(list)); // 10 // 再添加9个元素,塞满集合 for (int i = 1; i < 10; i++) { list.add(i); } System.out.println("list元素个数: " + list.size()); // 10 System.out.println("list的容量: " + getCapacity(list)); // 10 // 再添加一个元素(第11次添加) list.add(10); System.out.println("list元素个数: " + list.size()); // 11 System.out.println("list的容量: " + getCapacity(list)); // 15 } // 使用反射获取ArrayList集合的私有字段elementData, // elementData是一个Object数组,是ArrayList的底层实现;elementData数组的长度即为集合的容量 public static Integer getCapacity(ArrayList<?> list) throws Exception { Field field; field = list.getClass().getDeclaredField("elementData"); field.setAccessible(true); Object[] objArray = (Object[]) field.get(list); return objArray.length; } }
3、ArrayList的源码(jdk1.8.0_111)
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable private static final int DEFAULT_CAPACITY = 10; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } 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); } } private void ensureCapacityInternal(int minCapacity) { // elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA表示:集合通过空参构造创建,并且没有扩容过,容量为0 // 第1次调用add()方法后,调用ensureCapacityInternal(1),此时elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,所以minCapacity=10// 第11次add()方法后,调用ensureCapacityInternal(11),minCapacity=11 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // DEFAULT_CAPACITY=10 } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // 第11次add()方法后,minCapacity=11,elementData.length=10,达到扩容条件 if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); // 容量扩充为原来的1.5倍 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } }
另外可以参考:
posted on 2019-03-05 23:52 wenbin_ouyang 阅读(643) 评论(0) 编辑 收藏 举报