List接口的具体实现类:ArrayList、LinkedList、Vector
ArrayList实现类的使用:
1.ArrayList中参数可以是任何元素,包括null值
2.ArrayList中的参数是可以重复的
3.ArrayList底层是通过数组进行存储的
4.ArrayList中存储数据是有序的(输出顺序与输入顺序一致)
ArrayList arrayList = new ArrayList();
arrayList.add("jack");
arrayList.add("tom");
arrayList.add(null);
arrayList.add("mary");
arrayList.add(null);
System.out.println("arrayList = " + arrayList); // [jack, tom, null, mary, null]
ArrayList底层源码分析:
ArrayList中维护了一个Object[]类型的数组,通过数组存取数据
transient Object[] elementData; //transient表示瞬间、短暂的,该属性不会被序列化
ArrayList类中提供了无参构造器和有参构造器,并规定了扩容机制
public ArrayList(int initialCapacity); //指定大小的构造器
// 初始elementData容器大小为指定大小,如果需要扩容,则直接扩容elementData为1.5倍
public ArrayList(); // 无参构造器
// 初始elementData容器大小为0;首次添加后,容器大小为10;如果需要再次扩容,则扩容为1.5倍
调用ArrayList中的无参构造器进行创建对象:
// 源码解读:
ArrayList arrayList = new ArrayList();
/** 调用无参构造器,创建空数组elementData,size=0
* public ArrayList() {
* this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
* }
* private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
*/
for(int i = 0; i < 10; i++) {
arrayList.add(i);
}
/** 向数组中添加元素,执行arrayList.add方法
* public boolean add(E e) {
* // 首先判断是否需要对数组进行扩容处理
* ensureCapacityInternal(size + 1); // Increments modCount!!
* // 后进行数组元素赋值
* elementData[size++] = e;
* return true;
* }
*/
/** 首次添加元素(数组size=0)或数组长度不够用时,先进行扩容处理
// 先调用ensureCapacityInternal方法
* private void ensureCapacityInternal(int minCapacity) {
* // 确定数组需要进行扩容并计算数组扩容的大小
* ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
* }
// 调用ensureExplicitCapacity方法,确定数组需要进行扩容
* private void ensureExplicitCapacity(int minCapacity) {
* //记录数组被修改的次数,防止线程安全
* modCount++;
* // overflow-conscious code
* //最小容量-数组长度:当前数组的长度不够用的,调用grow方法进行扩容
* if (minCapacity - elementData.length > 0)
* grow(minCapacity);
* }
// 调用calculateCapacity方法,计算数组扩容大小
* private static int calculateCapacity(Object[] elementData, int minCapacity) {
* //判断是不是空数组
* if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
* //static final int DEFAULT_CAPACITY = 10; minCapacity = size+1
* return Math.max(DEFAULT_CAPACITY, minCapacity);
* }
* // 如果不是空数组,直接返回minCapacity=size+1
* return minCapacity;
* }
// 因此在calculateCapacity方法中,空数组扩容为10,不是空数组扩容为size+1
// 调用grow方法,进行数组扩容
* private void grow(int minCapacity) {
* // overflow-conscious code
* int oldCapacity = elementData.length;
* int newCapacity = oldCapacity + (oldCapacity >> 1);
* //数组第一次扩容时,oldCapacity=0,所以newCapacity=0;
* //之后数组进行扩容,oldCapacity!=0,所以newCapacity=1.5*oldCapacity
* if (newCapacity - minCapacity < 0)
* newCapacity = minCapacity;
* //newCapacity = 10
* if (newCapacity - MAX_ARRAY_SIZE > 0)
* newCapacity = hugeCapacity(minCapacity);
* // minCapacity is usually close to size, so this is a win:
* //底层调用copeOf进行数组扩容,拷贝之前的数据进入新的elementData数组,防止丢失数据
* elementData = Arrays.copyOf(elementData, newCapacity);
* }
*/
// 因此首次添加元素,将数组扩容为10,之后数组长度不够时,按照长度的1.5倍进行扩容
// 数组长度变化:10 -> 15 -> 22 -> ....
调用ArrayList的含参构造器进行创建对象:
ArrayList arrayList = new ArrayList(8);
/* 调用ArrayList中的有参构造器,创建一个指定大小的数组
* 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);
* }
* }
*/
for (int i = 0; i <= 10; i++) {
arrayList.add("hello" + i);
}
/* 向数组中添加元素,调用add方法
* 数组size=8,因此不需要直接对数组进行扩容处理
* 当i==8时,数组已满,需要进行扩容处理
* int newCapacity = oldCapacity + (oldCapacity >> 1):扩容为原来长度的1.5倍
*/
因此,调用无参构造器时,首先将数组扩容为10,之后按照1.5倍的速度对数组进行扩容;
调用含参构造器时,数组初始化为参数值,数组长度不够时,按照1.5倍的速度进行扩容;
此外,ArrayList中的方法没有关键字synchronized修饰,线程不安全。(多线程不使用ArrayList)