ArrayList底层源码分析之list.add方法

list.add方法源码分析

前言:本人第一次写文章,如果文章中有地方表达的不够正确或不清楚请指出来,我会加以改正。还请多多包含。
正文:相信在日常撸代码的过程中大家用到ArrayList集合中的场景不算少数,今天我也是突发奇想,想看下ArrayList是怎么实现的。这篇文章主要讲它的add()方法,在这之前先说明一下ArrayList中add()方法内使用到的属性,方便大家对add()方法的理解。

 //用来装载数据的容器,我们向list中添加的数据其实是存在这个数组当中的。
 transient Object[] elementData; 
 // 一个空的数组。 作用:用来初始化 elementData 数组。(数组的初始化有好几种方式,不知道可以百度的,这里就不说了。)
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 // 在不指定 list 长度大小情况下的默认初始长度
 private static final int DEFAULT_CAPACITY = 10;
 // Integer的最大值-8
 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 // 数组内元素的个数
 private int size;

以上就是在add() 方法种所使用到的对象了。
以下是add()的源码及每行代码的解释

    /**
     * Appends the specified element to the end of this list.(将指定的元素追加到列表的末尾)
     *	参数是你要添加的元素
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
    	// 这是一个方法 功能:用来检查是否首次向list中添加数据,并给定初始的容量大小(10)
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 向list中添加数据 并让size在原有的基础上+1(首次添加时size=0,添加完后size++ ,size的值就变成了1, size++ 是先执行,后运算。
        // ++size 是先运算,后执行。)
        elementData[size++] = e;
        // 无论如何都返回true
        return true;
    }

下边说 ensureCapacityInternal(size +1) 这个方法,在此方法中又调用了其他的方法,下边会依次列出并详解。

    private void ensureCapacityInternal(int minCapacity) {
    	// 在这一步它判断了是否是首次向list中添加数据,如果是首次那么它一定相等。(原因可以看ArrayList的无参构造方法,它里边有这样一句
    	// 	 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA 。	)
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        	// 这个方法返回两个值中最大的一个值,如果说首次添加数据那么它会返回 DEFAULT_CAPACITY(10)并赋值给 minCapacity 
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
		//这个方法用来检查是否需要扩容
        ensureExplicitCapacity(minCapacity);
    }

ensureExplicitCapacity(minCapacity);

    private void ensureExplicitCapacity(int minCapacity) {
    	// 这个变量用来记录list的修改次数,它是由ArrayList继承AbstractList抽象类得来的。
        modCount++;

        // overflow-conscious code
        //这里判断数组的长度 如果新元素添加后的数组长度大于当前数组的长度,那么他就需要进行一次1.5倍的扩容。
        if (minCapacity - elementData.length > 0)
        	//调用扩容方法 
            grow(minCapacity);
    }

grow(minCapacity);

	//增加elementData 数组的容量
    private void grow(int minCapacity) {
       //当前数组的长度
        int oldCapacity = elementData.length;
        //使用位运算符扩容至当前数组长度的1.5倍  newCapacity :扩容后的长度
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //检查扩容后的长度是否小于新元素添加后的数组长度,如果小于就将新元素添加后的长度赋值给 newCapacity 
        // newCapacity - minCapacity < 0 等同于 newCapacity < minCapacity
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //  MAX_ARRAY_SIZE 的值是:Integer.MAX_VALUE - 8 (这个方法基本用不到用到)。
        // hugeCapacity(int minCapacity)方法会在下段代码中贴出来
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 将当前数组以及要扩容的数组长度放到这个copyOf方法当中(不明白的话可以自己创建个数组然后用下这个方法,挺简单的。)
        // 在这一步就完成了数组的扩容了,如果不发生意外情况的话(意外情况就是 if (newCapacity - MAX_ARRAY_SIZE > 0)这一步),
        // 所扩容的长度将是原数组的 1.5 倍
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

hugeCapacity(minCapacity)

    private static int hugeCapacity(int minCapacity) {
    	// 检差参数是否小于零 否则抛出内存溢出异常 
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
         // 如果大于0的话 就比较是否大于  MAX_ARRAY_SIZE( MAX_ARRAY_SIZE值是:Integer.MAX_VALUE - 8)
         // 如果不大于就返回 MAX_ARRAY_SIZE 反之则返回 Integer.MAX_VALUE
        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
    }

到这一步其实关于扩容的就全部执行完勒,下边就回到最开始的地方

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!  
        // 开始执行这里,将元素添加到数组当中,然后size的值 +1 最终返回结果true
        elementData[size++] = e;
        return true;
    }

上边说的就是add(E e)这个方法了,下次有时间会把add(int index,E e)这个方法单独在写一个文章,文中如果有不对的地方,还请指正,大家一起进步成长。
如果觉得还不错的话就留个赞再走呗。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值