1.ArrayList简介

ArrayList的底层是数组队列,相当于动态数组。与Java中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用ensureCapacity操作来增加ArrayList实例的容量。这可以减少递增式再分配的数量。

ArrayList继承于AbstructList,实现了List,RandomAccess,Cloneable,Java.io.Serializable这些接口。

public class ArrayList extends AbstructList implements List,RandomAccess,Cloneable,java.io.Serializable{

}

RandomAccess是一个标志接口,表明实现这个接口的List集合是支持快速随机访问的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。

ArrayList实现了Cloneable接口,即覆盖了函数Clone(),能被克隆。

ArrayList实现了java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

1.1ArrayList和Vector的区别?

1.ArrayList是List的主要实现类,底层使用Object[ ]存储,适用于频繁地查找工作,线程不安全。

2.Vector是List的古老实现类,底层使用Object[ ]存储,线程安全的。

1.2ArrayList与LinkedList区别?

1.是否保证线程安全:ArrayList和LinkedList都是不同步的,也就是不保证线程安全;

2.底层数据结构:ArrayList底层使用的是Object数组;LinkedList底层使用的是双向链表数据结构;

3.插入和删除是否受元素位置的影响:

ArrayList采用数组存储,所以插入和删除元素的时间复杂度受元素位置影响。比如执行add(E e)方法的时候,ArrayList会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是,如果要在指定位置插入或者删除元素的话(add(int index,E element))时间复杂度就为O(n-i)。因为在进行上述操作的时候集合中第i和第i个元素之后的(n-i)个元素都要执行向后或者向前移一位的操作。

LinkedList采用链表存储 ,所以对于add(E e)方法的插入,删除元素时间复杂度不受元素位置的影响,近似O(1),如果要是在指定位置i插入和删除元素的话(add (int index,E element))时间复杂度近似为O(n)因为需要先移动到指定位置再插入。

4.是否支持快速随机访问:LinkedList不支持高效的随机元素访问,而ArrayList支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。

5.内存空间占用:ArrayList的空间浪费主要体现在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。

2.ArrayList核心源码解读

package java.util;

import java.util.function.Consumer;

import java.util.function.Predicate;

import java.util.function.UnaryOperator;

public class ArrayList extends AbstractList

implements List, RandomAccess, Cloneable, java.io.Serializable

{

private static final long serialVersionUID = 8683452581122892189L;

/**

* 默认初始容量大小

*/

private static final int DEFAULT_CAPACITY = 10;

/**

* 空数组(用于空实例)。

*/

private static final Object[] EMPTY_ELEMENTDATA = {};

//用于默认大小空实例的共享空数组实例。

//我们把它从EMPTY_ELEMENTDATA数组中区分出来,以知道在添加第一个元素时容量需要增加多少。

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**

* 保存ArrayList数据的数组

*/

transient Object[] elementData; // non-private to simplify nested class access

/**

* ArrayList 所包含的元素个数

*/

private int size;

/**

* 带初始容量参数的构造函数(用户可以在创建ArrayList对象时自己指定集合的初始大小)

*/

public ArrayList(int initialCapacity) {

if (initialCapacity > 0) {

//如果传入的参数大于0,创建initialCapacity大小的数组

this.elementData = new Object[initialCapacity];

} else if (initialCapacity == 0) {

//如果传入的参数等于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;

}

/**

* 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。

*/

public ArrayList(Collection c) {

//将指定集合转换为数组

elementData = c.toArray();

//如果elementData数组的长度不为0

if ((size = elementData.length) != 0) {

// 如果elementData不是Object类型数据(c.toArray可能返回的不是Object类型的数组所以加上下面的语句用于判断)

if (elementData.getClass() != Object[].class)

//将原来不是Object类型的elementData数组的内容,赋值给新的Object类型的elementData数组

elementData = Arrays.copyOf(elementData, size, Object[].class);

} else {

// 其他情况,用空数组代替

this.elementData = EMPTY_ELEMENTDATA;

}

}

/**

* 修改这个ArrayList实例的容量是列表的当前大小。 应用程序可以使用此操作来最小化ArrayList实例的存储。

*/

public void trimToSize() {

modCount++;

if (size < elementData.length) {

elementData = (size == 0)

? EMPTY_ELEMENTDATA

: Arrays.copyOf(elementData, size);

}

}

//下面是ArrayList的扩容机制

//ArrayList的扩容机制提高了性能,如果每次只扩充一个,

//那么频繁的插入会导致频繁的拷贝,降低性能,而ArrayList的扩容机制避免了这种情况。

/**

* 如有必要,增加此ArrayList实例的容量,以确保它至少能容纳元素的数量

* @param minCapacity 所需的最小容量

*/

public void ensureCapacity(int minCapacity) {

//如果是true,minExpand的值为0,如果是false,minExpand的值为10

int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)

// any size if not default element table

? 0

// larger than default for default empty table. It's already

// supposed to be at default size.

: DEFAULT_CAPACITY;

//如果最小容量大于已有的最大容量

if (minCapacity > minExpand) {

ensureExplicitCapacity(minCapacity);

}

}

//得到最小扩容量

private void ensureCapacityInternal(int minCapacity) {

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

// 获取“默认的容量”和“传入参数”两者之间的最大值

minCapacity = Math.max(D