ArrayList

75 阅读2分钟

List

List集合类中元素有序(添加取出顺序一致),且可重复

常用方法

//在指定位置添加元素
list.add(1,"jack");

//获取指定位置的元素
list.get(1);

//返回obj在集合中首次出现的位置
list.indexOf("jack");

//返回obj在集合中最后出现的位置
list.lastIndexOf("jack");

//替换index位置的元素
list.set(1,"tom");

//返回子集合,前闭后开
list.subList(0,2);

遍历方式

除了Collection的两种方式,还可以用普通for循环,因为List底层是用数组实现的

for (int i =0; i<list.size(); i++){
	System.out.println(list.get(i));
}

ArrayList

  1. 可以加入null
  2. 由数组实现数据存储的
  3. ArrayList基本等同于Vector,但是ArrayList是线程不安全的,

ArrayList源码分析

结论

  1. ArrayList中维护的是一个Object数组elementData
  2. 创建ArrayList对象时,若使用的是无参构造,则elementData的容量为0,第一次添加,扩容为10,若要再次扩容,则扩容1.5倍
  3. 若使用指定大小的构造器,扩容时直接扩容1.5倍

源码

public class ArrayList<E>{
	//默认仓库容量为10
	private static final int DEFAULT_CAPACITY = 10;
	//空数组
	private static final Object[] EMPTY_ELEMENTDATA = {};
	//默认空数组
	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	//数据域
	transient Object[] elementData;
	//当前数组存放元素数量
	private int size;



//有参构造,参数为list初始容量

public ArrayList(int initialCapacity) {  
    if (initialCapacity > 0) {
	    //创建一个容量为 形参大小 的数组  
        this.elementData = new Object[initialCapacity];  
    } else if (initialCapacity == 0) {
	    //若形参大小为0,相当于无参构造,数据域等于空数组  
        this.elementData = EMPTY_ELEMENTDATA;  
    } else { 
	    //形参为负数,抛出异常 
        throw new IllegalArgumentException("Illegal Capacity: "+  
                                           initialCapacity);  
    }  
}

//无参构造
public ArrayList() {  
	//数据域等于默认的空数组
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;  
}

//添加元素
public boolean add(E e) {  
    ensureCapacityInternal(size + 1);  // size+1=当前需要的最小容量
    elementData[size++] = e;  
    return true;  
}
//保证容量足够
private void ensureCapacityInternal(int minCapacity) {  
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));  
}

//计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {  
	//如果数据域等于默认的空数组,就说明是无参构造
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {  
	    //返回两个数较大的那一个,一般是默认容量10
        return Math.max(DEFAULT_CAPACITY, minCapacity);  
    }
    //否则返回当前需要的最小容量
    return minCapacity;  
}

//检查是否要扩容
private void ensureExplicitCapacity(int minCapacity) {  
    modCount++;  
  
    // 如果当前需要的最小容量大于数组容量,也就是说数组放不下了,扩容
    if (minCapacity - elementData.length > 0)  
        grow(minCapacity);  
}
//扩容
private void grow(int minCapacity) {  
    // 保存原来容量
    int oldCapacity = elementData.length;  
    //新容量为原来的1.5倍,>>1相当于*2
    int newCapacity = oldCapacity + (oldCapacity >> 1);  
    //如果新容量还是不够,那就让minCapacity为新容量
    if (newCapacity - minCapacity < 0)  
        newCapacity = minCapacity;  
    //如果新容量超过预设的最大容量,我也不知道干了个啥
    if (newCapacity - MAX_ARRAY_SIZE > 0)  
        newCapacity = hugeCapacity(minCapacity);  
    // 将数据域数组扩容
    elementData = Arrays.copyOf(elementData, newCapacity);  
}  
  

}