ArrayList集合、Vector源码分析(JDK21)

ArrayList类中的属性

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    @java.io.Serial
    private static final long serialVersionUID = 8683452581122892189L;
 
    /**
     * DEFAULT_CAPACITY表示集合默认的初始容量
     */
    private static final int DEFAULT_CAPACITY = 10;
 
    /**
     * 空数组EMPTY_ELEMENTDATA,在使用有参构造方法时传递0进去,创建ArrayList集合时就会使用这个数组
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};
 
    /**
        默认容量的空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 
    /**
     * 集合中真实存储元素的数组elementData
     */
    transient Object[] elementData; // non-private to simplify nested class access
 
    /**
     * 集合中元素的个数
     * @serial
     */
    private int size;    //int类型的成员变量初始值为0

ArrayList类中的构造方法

无参构造方法

使用无参构造方法创建ArrayList集合时,默认初始化容量为 0

第一次调用add方法添加元素时ArrayList的容量初始化为 10

    public ArrayList() {
        //将成员变量中的 默认容量的空数组 赋值给 真实存储元素的数组
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

无参构造方法创建的对象:添加方法

第一次添加数据:

在main方法中:

package test;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        //第一次添加元素
        list.add("zhangsan");

    }
}

第一次向集合中添加数据的流程:

  • 一级一级的调用下去

    public boolean add(E e) {
        modCount++;    //记录对当前集合操作的次数
        add(e, elementData, size);    //size为集合中元素的个数
        return true;
    }

--------------------------------------------

    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)  //如果集合的size == elementData数组的长度,就扩容
            elementData = grow();  //返回新的数组并赋值给elementData 
        //将要添加的元素 添加 到数组中有数据的下一个位置
        elementData[s] = e;
        size = s + 1;          // size = 0 + 1
    }


-------------------------------------------------------------

    private Object[] grow() {
        return grow(minCapacity:size + 1);   //需要的最小容量:0 + 1
    }

----------------------------------------------------------------

        //minCapacity:是ArrayList集合需要的最小容量
    private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;    //获取数组的原容量   0
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

结论:第一次添加元素时,会扩容为10

第二次添加数据:
  • 第二次添加元素也还不会扩容

main方法中:

package test;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        //第一次添加元素
        list.add("zhangsan");
        //第二次添加元素
        list.add("lisi");
    }
}

第二次添加元素的执行流程:

    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);   //size是集合的长度,现在size=1
        return true;
    }

----------------------------------------------------------

    private void add(E e, Object[] elementData, int s) {  //s=1
        if (s == elementData.length)    //  1 != 10  没存满,不执行
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }
第十一次添加数据:

ArrayList集合的扩容策略:此时ArrayList集合内部的数组不够存储新元素了,会扩容为原来的1.5倍

main方法中:

package test;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        //第一次添加元素
        list.add("zhangsan");
        //第二次添加元素
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        //第十一次添加元素
        list.add("lisi");

    }
}

第十一次添加元素的流程:

    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);      //此时size = 10
        return true;
    }

----------------------------------------------

    private void add(E e, Object[] elementData, int s) {   //s=10
        //当集合中元素个数等于数组长度时会扩容  10 == 10 
        if (s == elementData.length)    
            elementData = grow();    //扩容
        elementData[s] = e;
        size = s + 1;
    }


--------------------------------------------------------
    private Object[] grow() {
        return grow(size + 1);    10 + 1 = 11
    }


--------------------------------------------------------------

    private Object[] grow(int minCapacity) {      //此时minCapacity=11
        int oldCapacity = elementData.length;  //获取原容量的长度 oldCapacity=10
        // oldCapacity > 0 :执行
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //计算新容量:新容量newCapacity是在原容量的基础上扩容1.5倍
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth 11-10=1 */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

-----------------------------------------------------------------
                               //   10        最小增长:1       预期增长:5
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        //新的容量newCapacity是在原容量的基础上扩容1.5倍
        //prefLength = 10 + 5                     1           5
        int prefLength = oldLength + Math.max(minGrowth, prefGrowth);
        if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
            return prefLength;       //return 15
        } else {
            // put code cold in a separate method
            return hugeLength(oldLength, minGrowth);
        }
    }


--------------------------------------------------------------------------
    //回去继续执行grow(int minCapacity)方法
    private Object[] grow(int minCapacity) {      //此时minCapacity=11
        int oldCapacity = elementData.length;  //获取原容量的长度 oldCapacity=10
        // oldCapacity > 0 :执行
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //新的容量newCapacity是在原容量的基础上扩容1.5倍
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth 11-10=1 */
                    oldCapacity >> 1           /* preferred growth */);
                    //将原数组复制到长度为15的新数组中,并将新数组复制给elementData 
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }
-----------------------------------------------------------
    //回去grow()方法
    private Object[] grow() {
        return grow(size + 1);
    }
-------------------------------------------------------------
//回去添加元素
    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

--------------------------------------------------------
//返回
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

有参构造方法

main方法:

   
public class Test {
    public static void main(String[] args) {
        ArrayList list = new ArrayList(20);  //创建一个指定初始容量为20的ArrayList集合
    }
}

有参构造方法源码:

内部创建了一个指定长度的数组 并赋值给了elementData

         //给定初始化容量initialCapacity
  public ArrayList(int initialCapacity) { //initialCapacity=20
        if (initialCapacity > 0) {
            //内部创建了一个长度为20的数组,并赋值给this.elementData
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            //如果传递的是0,就将空数组EMPTY_ELEMENTDATA 赋值给 this.elementData
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            //如果在构造方法中传递负数,就会抛出如下异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

有参构造方法创建的对象:添加方法

执行时调用的方法都和无参的一样

main方法:

package test;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>(20);
        list.add("lisi");

    }
}

执行流程:

    public boolean add(E e) {
        modCount++;   //对集合的操作次数+1
        add(e, elementData, size);  //size=0
        return true;
    }

-------------------------------------------------

    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)  //判断内部的数组满没满,满了就扩容  
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

ArrayList中的set方法

main方法:

package test;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("lisi");
        list.set(0,"李四");

    }
}

源码:

    public E set(int index, E element) {
        Objects.checkIndex(index, size);   //检查下标是否越界
        E oldValue = elementData(index);   //将index位置的元素取出来并保存
        elementData[index] = element;      //将修改后的元素存到index位置
        return oldValue;    //返回修改前的数据
    }

ArrayList集合的插入

main方法:

package test;

import java.util.ArrayList;

public class ArrayListTest1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        list.add(0,"zhangsan");
    }
}

插入方法的源码执行分析:

    public void add(int index, E element) { //index:0,element:"zhangsan"
        rangeCheckForAdd(index);  //检查下标
        modCount++;   //对集合的修改次数加+1
        final int s;
        Object[] elementData;
        //集合中的元素个数 等于 数组的长度时,才会扩容
        //       3      !=             10
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        //从elementData数组的index下标开始拷贝,拷贝到elementData数组中,从下一个位置开始放元素
        //将插入位置之后的元素都后移一位,包括插入位置的元素(通过数组的复制实现)
        System.arraycopy(elementData, index,   //index=0
                         elementData, index + 1,
                         s - index);              //拷贝多长 3-0=3个元素
        elementData[index] = element;   //将元素赋值给数组元素
        size = s + 1;    //个数+1
    }

ArrayLsit集合的remove((int  index)方法

main方法:

package test;

import java.util.ArrayList;

public class ArrayListTest1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("lisi");
        list.add("lisi");
        list.add("lisi");
        list.add(0,"zhangsan");
        list.remove(0);
    }
}

源码执行分析:

    public E remove(int index) {   index:0
        Objects.checkIndex(index, size);   //检查索引是否越界  index:0   size:4
        final Object[] es = elementData;  //将elementData数组赋值给es

        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
        fastRemove(es, index);  index:0

        return oldValue;
    }

------------------------------------------------------------------------
    private void fastRemove(Object[] es, int i) {    //i:0
        modCount++;
        final int newSize;
        //删除一个元素,所以集合长度-1,并赋值给newSize
        if ((newSize = size - 1) > i)    //newSize:3 > 0
            //将es数组中删除元素之后的元素都前移一个位置(通过数组的拷贝来实现)
            System.arraycopy(es, i + 1, es, i, newSize - i);
        //
        es[size = newSize] = null; //将最后一个位置置null
    }

Vector集合

main方法:

package test;

import java.util.List;
import java.util.Vector;

//Vector中所有的方法都使用了synchronized修饰,所有的方法都是线程安全的
//Vector的效率较低,已经很少使用,现在保证线程安全有了新手段
public class VectorTest1 {
    public static void main(String[] args) {
        //创建Vector集合
        //分析源码,看看初始化容量是多少
        List<String> list = new Vector<>();

        //分析源码,看Vector集合是怎么扩容的
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");
        list.add("7");
        list.add("8");
        list.add("9");
        list.add("10");
        list.add("11");  //扩容




    }
}

Vector集合的无参构造方法:

初始化容量为10

    public Vector() {
        this(10);     //调用重载的有参构造方法,并传入10
    }

-------------------------------------------------

    public Vector(int initialCapacity) {  initialCapacity:10
        this(initialCapacity, 0);         //继续调用重载的有参构造方法
    }

-----------------------------------------------------------------
                //        10                     0
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)     10 > 0   不执行
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        //开辟一个长度为10的Object类型的数组并赋值给elementData数组
        this.elementData = new Object[initialCapacity];  
        this.capacityIncrement = capacityIncrement;
    }

Vector集合扩容

源码执行流程:

Vector集合的扩容策略:每次扩容原来的2倍

    public synchronized boolean add(E e) {
        modCount++;
        add(e, elementData, elementCount);
        return true;
    }

----------------------------------------------------------
                     "11"                         10
    private void add(E e, Object[] elementData, int s) { 
        //如果不够存入元素就扩容
        if (s == elementData.length)   //10 == 10
            elementData = grow();
        elementData[s] = e;
        elementCount = s + 1;
    }

-----------------------------------------------------------
    private Object[] grow() {
        //elementCount集合中的元素个数
        return grow(elementCount + 1);   //10 + 1
    }
--------------------------------------------------------------

    private Object[] grow(int minCapacity) { //minCapacity:10
        int oldCapacity = elementData.length;  //获取数组的原容量:10
        
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity, /* minimum growth */
                capacityIncrement > 0 ? capacityIncrement : oldCapacity  //capacityIncrement:0
                                           /* preferred growth */);
        return elementData = Arrays.copyOf(elementData, newCapacity);
    }

---------------------------------------------------------
回去继续执行添加逻辑
    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;    
        elementCount = s + 1;
    }

    public synchronized boolean add(E e) {
        modCount++;
        add(e, elementData, elementCount);
        return true;
    }

.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值