ArrayList源码解析:ArraysList的字段属性和构造函数

ArrayList源码解析

arrayList就是动态数组,可以动态的添加和减少元组,实现了ICollection和Ilist接口以及灵活的设置数组的大小。

2. ArraysList的字段属性

	private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 保存数据的集合的默认长度
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 一个空的数组实例
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 也是一个空的数组实例,和EMPTY_ELEMENTDAT空数组相比是用于了解添加元素时数组膨胀多少。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 存储ArrayList存储的元素,集合的长度就是这个数组的长度。
     * 当elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA时将会清空ArraysList
     * 当添加第一个元素的时候,elementData将会扩展到DEFAULT_CAPACITY大小,也就是说在刚开始创建的时候不是10个,而是在第一次添加的时候才会变为大小10
     */
    transient Object[] elementData; // 不是私有的,方便其他类访问,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化。回想ArrayList的自动扩容机制,elementData数组相当于容器,当容器不足时就会再扩充容量,但是容器的容量往往都是大于或者等于ArrayList所存元素的个数。比如,现在实际有了8个元素,那么elementData数组的容量可能是8x1.5=12,如果直接序列化elementData数组,那么就会浪费4个元素的空间,特别是当元素个数非常多时,这种浪费是非常不合算的。所以ArrayList的设计者将elementData设计为transient,然后在writeObject方法中手动将其序列化,并且只序列化了实际存储的那些元素,而不是整个数组。见https://www.cnblogs.com/vinozly/p/5171227.html
    /**
     * 表示集合的长度
     */
    private int size;

3. 构造函数

通过指定initialCapacity,可以构造指定初始容量的集合。这里可以发现在源码中,通过区分参数区间来划分不同情况,而不是通过一种流程来直接得出相应的结果的思想很重要。

	public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
        }
    }

在无参构造函数中,将创建一个DEFAULTCAPACITY_EMPTY_ELEMENTDATA声明的数组,这里的数组容量是0,而不是很多人认为的10.当数组开始增加元素时才会扩容到10。

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

此构造函数,可以将已有的集合复制到ArrayList。当集合的大小为0的时候,则直接创建一个DEFAULTCAPACITY_EMPTY_ELEMENTDATA声明的数组,这里的数组容量是0。

public ArrayList(Collection<? extends E> c) {
    Object[] a = c.toArray();
    if ((size = a.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
            elementData = Arrays.copyOf(a, size, Object[].class);
            //copyOf用于拷贝数组元素。底层采用System.arraycopy实现,是一种本地方法。
        }
    } else {
        // replace with empty array.
        elementData = EMPTY_ELEMENTDATA;
    }
}
posted @ 2021-09-24 11:56  锤子布  阅读(67)  评论(0编辑  收藏  举报