jdk 1.8.0 系列源码 -- ArrayList

1,首先我们看一段代码

 ArrayList list = new ArrayList();//1
        list.add(1);//2
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        list.add(2,3.1);
        System.out.println(list);

我们平时都是直接喜欢new ArrayList(),用无参构造来实例化ArrayList,那么它的初始化容量是多少呢?

/**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

从上面的代码可以看出,无参构造来实例化的ArrayList,其实是一个空数组。
当我们代码走到2处,即list.add(1),

   public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 扩容
        //size为已使用的数组大小,此时为0
        elementData[size++] = e;
        return true;
    }

再看ensureCapacityInternal(size + 1) 源码

private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

第一次添加,size = 0,因此minCapacity=1,elementData为一个大小为0的数组。进入calculateCapacity(elementData, minCapacity)

  private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

上面说过,初始化的时候ArrayList,this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;因此会进入到Math.max(DEFAULT_CAPACITY, minCapacity)方法,这里就可以知道,为什么ArrayList的初始化容量为10了,因为DEFAULT_CAPACITY=10。

	//默认初始化容量
  private static final int DEFAULT_CAPACITY = 10;

接着到上一层的ensureExplicitCapacity(int minCapacity)方法,这时minCapacity=10了。进入此方法:

	//minCapacity=1
 private void ensureExplicitCapacity(int minCapacity) {
 		//modCount为数组修改的次数
        modCount++;

        // minCapacity - elementData.length相当于10-0>0(仅是第一次添加元素的时候)
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

由于大于0,进入 grow(minCapacity),minCapacity=10

   private void grow(int minCapacity) {
        // 现在数组的长度,为0
        int oldCapacity = elementData.length;
        //扩容后的长度
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
      //复制,返回扩容后的数组
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

Arraylist每次都按照1.5倍扩容就是来自算法oldCapacity >> 1,由于oldCapacity=0,所以,newCapacity=0,
接着if (newCapacity - minCapacity < 0)满足条件,newCapacity=10,
接着扩容数组elementData = Arrays.copyOf(elementData, newCapacity)后,elementData就是一个容量为10的数组了。
扩容完后就是赋值了,返回到最开始的代码:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //赋值
        elementData[size++] = e;
        return true;
    }

现在,一个添加操作就已经完成了。从代码可以看出,添加操作每次都会根据minCapacity - elementData.length > 0条件判断是否需要扩容,不需要则直接赋值操作。

我们再来看一下ArrayList的属性

 	//无参初始化默认容量
    private static final int DEFAULT_CAPACITY = 10;
	//
    private static final Object[] EMPTY_ELEMENTDATA = {};
	//默认空数组
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	//数组
    transient Object[] elementData;  
    //已使用数组容量
    private int size;

我们会发现有两个空数组EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA,这两个有啥区别??
DEFAULTCAPACITY_EMPTY_ELEMENTDATA是ArrayList()时使用,
EMPTY_ELEMENTDATA是ArrayList(0)时使用,并且走的时1.5倍的扩容。
并且写代码别ArrayList list = new ArrayList(0);这样初始化,因为这样初始化,添加元素会频繁扩容。
以上为添加方法的源码讲解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值