ArrayList源码分析(JDK1.8)

ArrayList源码分析


1.继承结构

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

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


2.属性:

//版本号
private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 默认容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 空对象数组
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 默认空数组
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 元素数组
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
    * 容量
     */
    private int size;

transient 关键字

  • Java的Serializable提供了一种序列化对象实例的机制。当序列化对象时,可能有一个特殊的对象数据成员,我们不想用Serializable机制来保存它。为了在一个特定对象的一个域上关闭Serializable,可以在这个域前加上关键字transient。
  • transient是Java语言的关键字,用来表示一个域不是该对象序列化的一部分。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。

3.构造方法:

  • 无参的构造方法。
    /**
     * 说明了默认会给10的大小,所以说一开始arrayList的容量是10.
     * ArrayList中储存数据的其实就是一个数组,这个数组就是elementData
     */
    public ArrayList() {
       //设置元素数组为空 
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

有参数的构造器:


    /**
     *   传入一个初始化大小的一个参数。
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
        //如果大于0将自定义的容量作为初始化elementData的大小
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
        //如果等于0将将数组赋值为空对象数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
         //判断如果自定义大小的容量小于0,则报下面这个非法数据异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

有参数的构造方法:

     //集合参数构造函数
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray(); // 转化为数组
        if ((size = elementData.length) != 0) {// 参数为非空集合
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)//// 是否成功转化为Object类型数组
                elementData = Arrays.copyOf(elementData, size, Object[].class);// 不为Object数组的话就进行复制
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

核心方法:
1.add函数:

     //添加元素
  public boolean add(E e) {
    //(ensureCapacityInternal)为确保elementData数组有合适的大小,是否需要扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
     //如果创建ArrayList时用的是无参构造器,则第一次插入时会进行一次扩容并且扩到默认数组大小10
     //然而如果是使用带有容量参数的构造器且initialCapacity=0时,则不会进行这一步,直接扩展数组容量为minCapacity
      //这就导致一个结果,扩容之后带参数的构造器的数组length为1,而默认的为10
    //所以,带容量参数的初始化时注意自己需要的大小
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }
  private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        // 超出了数组可容纳的长度,则进行动态扩展  
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
//grow函数会对数组进行扩容
    private void grow(int minCapacity) {
        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);
    }

容量的拓展将导致数组元素的复制,多次拓展容量将执行多次整个数组内容的复制。若提前能大致判断list的长度,调用ensureCapacity调整容量,将有效的提高运行速度。

可以理解提前分配好空间可以提高运行速度,但是测试发现提高的并不是很大,而且若list原本数据量就不会很大效果将更不明显。


set函数:

  public E set(int index, E element) {
        rangeCheck(index);//检查是否越界
        E oldValue = elementData(index);//拿到原来的值

        elementData[index] = element;//赋新值

        return oldValue;//返回原来的值。
    }

ArrayList有其特殊的应用场景,与LinkedList相对应。其优点是随机读取,缺点是插入元素时需要移动大量元素,效率不太高。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值