JDK1.8 ArrayList 扩容详解

arraylist这个数据结构比较简单,总体来说,arraylist 底层结构是数组,他的很多方法都是从数组上面演变而来的,下面分析下arraylist的扩容机制,

每次在add()一个元素时,arraylist都需要对这个list的容量进行一个判断。如果容量够,直接添加,否则需要进行扩容。在1.8 arraylist这个类中,扩容调用的是grow()方法,通过grow()方法中调用的Arrays.copyof()方法进行对原数组的复制,在通过调用System.arraycopy()方法进行复制,达到扩容的目的

几个重要的初始化值

 
  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

几个重要的方法

一个空的构造方法

 
  1. 默认数组的长度为10

  2. public ArrayList() {

  3. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

  4. }

添加元素的方法,

 
  1. public boolean add(E e) {

  2. 扩充长度,在原来的大小上面加1

  3. // Increments modCount!!

  4. ensureCapacityInternal(size + 1);

  5. 添加元素

  6. elementData[size++] = e;

  7. return true;

  8. }

确认内部容量

 
  1. private void ensureCapacityInternal(int minCapacity) {

  2. ensureExplicitCapacity(

  3. calculateCapacity(elementData, minCapacity));

  4. }

计算容量

 
  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. }

确认扩展容量

 
  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. }

扩展方法

 
  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. }

数组工具类中的复制方法

 
  1. public static <T> T[] copyOf (T[] original, int newLength) {

  2. return (T[]) copyOf(original, newLength, original.getClass());

  3. }

具体的复制方法

 
  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.  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值