Java-ArrayList

ArrayList(部分内容摘取于:优秀参考文章

【介绍】

ArrayList就是动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了动态的增加和减少元素,实现了ICollection和IList接口,灵活的设置数组的大小等好处

ArrayList封装了一系列操作,如增删改查,对比使用传统的数组方便了很多,因为java代码已经替我们写好了,我们直接用即可。


【使用】

一、构造方法:

(1)无参构造器:返回一个初始容量为0的空列表,扩容是在第一次add的时候进行的

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

(2)传入一个 int类型 的有参构造器:返回一个以你传入的参数作为初始容量的空列表

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);
    }
}

(3)构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。

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);
        }
    } else {
        // replace with empty array.
        elementData = EMPTY_ELEMENTDATA;
    }
}

二、常用方法:

以实现List接口为例:

Java-ArrayList


【底层操作机制源码分析】

(1)ArrayList中维护了一个Object类型的数组 elementData

(2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次add,则扩容为10,如果后续再次需要扩容,则扩容为原容量的1.5倍(看源码,有移位操作)

(3)如果使用的是指定大小的构造器,则初始容量为指定的大小,如果后续需要扩容,则扩容为1.5倍。

ArrayList类的相关方法和属性:

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	//无参构造器:elementData被赋值为一个空的对象数组
}

transient Object[] elementData; //transient(短暂的意思):对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。
private static final int DEFAULT_CAPACITY = 10; //字段意思:默认容量,值为10
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //就是一个空的对象数组
private int size; //初始值为0

无参构造器第一次 add:

public boolean add(E e) {
    modCount++;  //该字段表示list结构上被修改的次数
    add(e, elementData, size);
    return true;
}


private void add(E e, Object[] elementData, int s) {
	//判断元素个数 size 是否等于数组elementData的长度,如果相等,则进行扩容操作
    if (s == elementData.length) //s=size=初始值0;elementData数组一开始也是空数组,长度为0
        elementData = grow();
    elementData[s] = e;  //将元素添加进数组中
    size = s + 1;  //添加完成后,size加1
}

private Object[] grow() {
    return grow(size + 1); //传入size + 1 = 0+1 = 1
}

private Object[] grow(int minCapacity) { //最小容量为 1(size + 1)
    int oldCapacity = elementData.length; //旧容量为空数组长度0
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //第一次add,这里都是fasle,进入else
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity, /* minimum growth */
                oldCapacity >> 1           /* preferred growth */);
        return elementData = Arrays.copyOf(elementData, newCapacity);
    } else { //返回一个新的对象数组给elementData,容量是DEFAULT_CAPACITY, minCapacity这两个的最大值,故第一次扩容,容量是10
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
    }
}

无参构造器第十一次add:

public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
    // assert oldLength >= 0
    // assert minGrowth > 0

    int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
    if (newLength - MAX_ARRAY_LENGTH <= 0) {
        return newLength;
    }
    return hugeLength(oldLength, minGrowth);
}

有参构造器:

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);
    }
}

注意使用有参构造器传入参数0和使用无参构造器的区别:

//它们的扩容机制不太一样
    List list2 = new ArrayList(0); //this.elementData = EMPTY_ELEMENTDATA;
    List list3 = new ArrayList(); //this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

扩容方法:(Arrays.copyOf()方法详解-jdk1.8)

return elementData = Arrays.copyOf(elementData, newCapacity);

modCount参数:

参考文章:https://blog.csdn.net/u012926924/article/details/50452411

上一篇:python – 使用两个不同的decorator实现来装饰所有类方法的Metaclass


下一篇:java – 记录已删除对象的BlockingQueue装饰器