JDK1.8 ArrayList 扩容详解

arraylist这个数据结构比较简单,总体来说,arraylist 底层结构是数组,他的很多方法都是从数组上面演变而来的,下面分析下arraylist的扩容机制,
每次在add()一个元素时,arraylist都需要对这个list的容量进行一个判断。如果容量够,直接添加,否则需要进行扩容。在1.8 arraylist这个类中,扩容调用的是grow()方法,通过grow()方法中调用的Arrays.copyof()方法进行对原数组的复制,在通过调用System.arraycopy()方法进行复制,达到扩容的目的
几个重要的初始化值
[java] view plain copy
  1. 存储数组元素的缓冲区  
  2. // non-private to simplify nested class access  
  3. transient Object[] elementData;   
  4. 默认空数组元素  
  5. private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};  
  6. 默认初始化容量  
  7. private static final int DEFAULT_CAPACITY = 10;  
  8. 数组的大小  
  9. private int size;  
  10. 记录被修改的次数  
  11. protected transient int modCount = 0;  
  12. 数组的最大值  
  13. private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8  
几个重要的方法
一个空的构造方法
[java]  view plain  copy
  1. 默认数组的长度为10  
  2. public ArrayList() {  
  3.     this.elementData  = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;  
  4. }  
添加元素的方法,
[java]  view plain  copy
  1. public boolean add(E e) {  
  2. 扩充长度,在原来的大小上面加1  
  3. // Increments modCount!!  
  4.     ensureCapacityInternal(size + 1);    
  5. 添加元素  
  6.     elementData[size++] = e;  
  7.     return true;  
  8. }  
确认内部容量
[java]  view plain  copy
  1. private void ensureCapacityInternal(int minCapacity) {  
  2.     ensureExplicitCapacity(  
  3. calculateCapacity(elementData, minCapacity));  
  4. }  
计算容量
[java]  view plain  copy
  1. private static int calculateCapacity (Object[] elementData, int minCapacity) {  
  2. 如果这个数组等于空,返回最大的容量,否则,还是原来的容量  
  3.     if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {  
  4.         return Math.max(DEFAULT_CAPACITY, minCapacity);  
  5.     }  
  6.     return minCapacity;  
  7.     }  
确认扩展容量
[java]  view plain  copy
  1. private void ensureExplicitCapacity(int minCapacity) {  
  2. 修改次数加1  
  3.     modCount++;  
  4. 如果容量不够,调用增加容量方法  
  5.     // overflow-conscious code  
  6.     if (minCapacity - elementData.length > 0)  
  7.         grow(minCapacity);  
  8. }  
扩展方法
[java]  view plain  copy
  1. private void grow(int minCapacity) {  
  2.     // overflow-conscious code  
  3. 获取原来数组容量的长度  
  4.     int oldCapacity = elementData.length;  
  5. 新增加的容量长度为原来容量的1.5倍  
  6.     int newCapacity = oldCapacity + (oldCapacity >> 1);  
  7. 新容量比老容量小,那么新的容量就是老的容量  
  8.     if (newCapacity - minCapacity < 0)  
  9.         newCapacity = minCapacity;  
  10. 新创建的容量超过数组的最大值。抛出异常  
  11.     if (newCapacity - MAX_ARRAY_SIZE > 0)  
  12.         newCapacity = hugeCapacity(minCapacity);  
  13.     // minCapacity is usually close to size, so this is a win:  
  14.   
  15. 调用复制方法,在原来元素上增加容量,这就是传说中的可变集合。用新长度复制原数组。  
  16.     elementData = Arrays.copyOf(elementData, newCapacity);  
  17. }  
数组工具类中的复制方法
[java]  view plain  copy
  1. public static <T> T[] copyOf (T[] original, int newLength) {  
  2.     return (T[]) copyOf(original, newLength, original.getClass());  
  3. }  
具体的复制方法
[java]  view plain  copy
  1. public static <T,U> T[] copyOf(U[] original, int newLength,   
  2. Class<? extends T[]> newType) {  
  3.     @SuppressWarnings("unchecked")  
  4. 获得者数组对象  
  5.     T[] copy = ((Object)newType == (Object)Object[].class)  
  6.         ? (T[]) new Object[newLength]  
  7.         : (T[]) Array.newInstance(newType.getComponentType(), newLength);  
  8.   
  9. 调用系统的方法增加数组容量  
  10.     System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));  
  11.     return copy;  
  12. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值