List是继承Collection接口的一个子接口,其主要的实现有ArrayList、LinkedList和Vector
一、ArrayList:
1、主要变量、常量等基本定义
int DEFAULT_CAPACITY :默认的初始容量,ArrayList会定义一个默认的初始容量,初始值为10
Object[] EMPTY_ELEMENTDATA = {}:默认空对象:ArrayList中对象数量为空时默认为{}
Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}:按介绍来说,任何带有 elementdata==defaultcapacity_empty_elementdata的ArrayList对象在调用Add之前都为EMPTY_ELEMENTDATA,也就是说如果新建一个空的ArrayList变量,则elementdata默认为该值
疑问:DEFAULTCAPACITY_EMPTY_ELEMENTDATA与EMPTY_ELEMENTDATA的区别在哪?当elementdata为EMPTY_ELEMENTDATA时是否还可以调用Add方法?
Object[] elementData:存储ArrayList对象
int size:ArrayList的长度
2、构造方法:
传入一个整型变量
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);
}
}
初始化时传入一个整型变量,如果这个变量大于零,会将elementData的长度设置为该整型变量,如果为0,则设置为空,即EMPTY_ELEMENTDATA,如果小于零,则会报IllegalArgumentException错误。
什么也不传入
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
如上述所说,当什么也不传入时,ArrayList会默认为DEFAULTCAPACITY_EMPTY_ELEMENTDATA
传入一个Collection接口的变量
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
由代码可以看出,首先我们把传入的变量赋值给elementData,当传入的变量长度(也就是现在elementData的长度)不为0的时候,判断传入的变量是否为Object[]类型的,如果不是则转化为Object类型。如果传入的变量长度为0,则为EMPTY_ELEMENTDATA。
3、常用方法
add 一个变量
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
我们可以看到,调用add方法首先会调用ensureCapacityInternal方法,我们先看一下这个方法
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
如果elementData的值为DEFAULTCAPACITY_EMPTY_ELEMENTDATA,那我们需要比较出DEFAULT_CAPACITY和minCapacity中的最大值,也就是DeFAULT_CAPACITY与当前的数组长度+1之间的最大值,然后调用ensureExplicitCapacity,那我们看一下ensureExplicitCapacity这个方法
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
我们发现这里多了一个以前没有提到过的变量modCount,而这个modCount是做什么用的呢?modCount代表的修改次数,主要是为了防止在多线程中该对象被其他线程修改,比如,一个线程在读取该对象,而另一个线程对该对象进行了增删操作,那样就会抛出异常。
然后如果传入的值减去现在该对象的长度大于零,那么就会调用grow这个方法,那么就有另外一个问题:为什么要比较DEFAULT_CAPACITY和minCapacity的大小呢?