JDK1.8源码阅读---ArrayList

一、简介

   ArrayList是基于数组实现的一个动态数组,其容量能自动增长。ArrayList不是线程安全的,多线程环境下考虑Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。

二、源码理解

2.1 类继承关系

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList继承AbstractList抽象父类,实现了List接口(规定了List的操作规范)、RandomAccess(可随机访问)、Cloneable(可拷贝)、Serializable(可序列化)

2.2 类属性

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
	//序列化版本号
    private static final long serialVersionUID = 8683452581122892189L;
    //默认数组容量
    private static final int DEFAULT_CAPACITY = 10;
    //空实例,默认为{},通过带参数构造器创建实例时使用
    static final Object[] EMPTY_ELEMENTDATA = {};
    //缺省空实例,采用ArrayList默认大小10创建的空实例
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    //用来存储真正的数据数组
    transient Object[] elementData; 
    //数组元素数量
    private int size;
    //最大数组容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
}

2.3 构造函数

  1. 有参构造器(初始化数组容量)

     public ArrayList(int initialCapacity) {
     		//如果initialCapacity大于0则根据指定的大小创造一个数组
            if (initialCapacity > 0) {
                this.elementData = new Object[initialCapacity];
            //如果initialCapacity等于0则将默认的空列表EMPTY_ELEMENTDATA赋值给elementData
            } else if (initialCapacity == 0) {
                this.elementData = EMPTY_ELEMENTDATA;
           //小于0则抛出参数异常
            } else {
                throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
            }
        }
    
  2. 无参构造器

     public ArrayList() {
     		//将DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组赋值给elementData
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
    
  3. 有参构造器(根据给定的集合)

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
           //如果elementData长度不等于0,并且不是Object类型数组时,则调用Arrays.copyOf复制一个Object类型数组,并复制给elementData
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            //如果数组大小等于0,则将EMPTY_ELEMENTDATA空数组赋值给elementData 
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
    

2.4 核心函数

  • add(E e):添加元素

    public boolean add(E e) {
    		//调用ensureCapacityInternal函数,确定数组的大小,size+1表示添加当前元素后数组的容量大小
            ensureCapacityInternal(size + 1); 
            //将数组size位置的元素设置为e
            elementData[size++] = e;
            return true;
        }
    
    private void ensureCapacityInternal(int minCapacity) {
    	//如果数组是默认的空数组,则将minCapacity与默认数组的容量大小比较,取最大的赋值给minCapacity(需要的数组容量值)
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
    	//确定是否需要数组扩容
        ensureExplicitCapacity(minCapacity);
    }
    
    private void ensureExplicitCapacity(int minCapacity) {
           //记录集合的修改次数
            modCount++;
    		//如果需要的数组容量大小大于当前数组大小,则调用grow()方法进行扩容
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }
    
    //这个方法是ArrayList这个类add方法的最后一步,主要做的就是确定size然后进行数组的copy与赋值
    //至于真正的copy,是由Arrays.copyOf调用System.arraycopy,最后完成copy这一步是个native方法去做的
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        //newCapacity当前数组容量,取原数组的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //如果暂定数组容量不满足指定容量minCapacity,则将minCapacity赋值给newCapacity
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //如果newCapacity大于最大容量,则调用hugeCapacity()方法确定最终值
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //调用Arrays.copyOf(原数组,数组大小),将数组copy形成新的数组重新复制,从而完成数组的扩容
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    
    //超容量数组大小判断
    private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            //如果minCapacity 大于MAX_ARRAY_SIZE则取Integer的最大值,如果小于则取MAX_ARRAY_SIZE
            return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
        }
    

    通过add方法的阅读可以发现,几个重要的点

    • ArrayList本质上是个数组,数据存储是由数组来完成,ArrayList只不过是进行了封装、扩展功能
    • 数组容量最大为Integer的最大值
    • 添加元素内部实现,其实是建立的新的数组,所以再创建ArrayList时最好有个预估容量大小,不然会造成频繁的扩容
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值