1.继承关系
从图中可以看出Arraylist继承AbstractList类(AbstractList继承了AbstractCollection类,同时实现了list类),同时实现了Serializable、List(继承了collection接口,collection接口继承了Iterable接口)、Cloneable、RandomAccess(快速随机访问)
2.属性
重要的属性
- Object[] elementData 对象数组
- DEFAULT_CAPACITY 数组默认大小10
- size数组大小
- modCount修改次数 在AbstractList中定义
3.构造方法
ArrayList()
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
在注释上面可以看到Constructs an empty list with an initial capacity of ten.构造一个初始为10的空数组,但是实际上是将定义的常量空数组赋值给elementData,如果使用无参的构造函数实际上是在add方法中添加的长度。
ArrayList(Collection<? extends E> c)
public ArrayList(Collection<? extends E> c) {
//collection转array
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// defend against c.toArray (incorrectly) not returning Object[]
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
if (elementData.getClass() != Object[].class)
//判断集合是否是Object类型,如果不是则转换成object类型
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
根据集合来创建arraylist,最终保存的是object的数组或者一个空数组
elementData = Arrays.copyOf(elementData, size, Object[].class);
主要是为了解决https://bugs.openjdk.java.net/browse/JDK-6260652这个bug
ArrayList(int initialCapacity)
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);
}
}
根据传入的值初始化数组大小
常用方法
add
add方法向外提供两种,第一种是add(E e)默认往最后一个位置新增,第二种add(int index, E element),向指定位置新增
add(E e)
public boolean add(E e) {
//每操作一次modCount++,主要是因为Arraylist不是线程安全类
modCount++;
add(e, elementData, size);
return true;
}
//重载的私有的add
private void add(E e, Object[] elementData, int s) {
//插入的位置等于数组长度就需要扩容
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
add(int index, E element)
public void add(int index, E element) {
//判断插入的时候是否越界,因为arraylist不是线程安全的,多线程的时候可能存在已经插入的情况
rangeCheckForAdd(index);
modCount++;
final int s;
Object[] elementData;
//考虑扩容
if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
//将原来index到末尾的值全部copy移到后面一位
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
elementData[index] = element;
size = s + 1;
}
扩容grow方法
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
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);
}
可以看出扩容是从原数组大小1.5倍和最小期望值大小中取最大,同时还需考虑越界问题
remove
向外提供的删除方法有两种,一个是remove(int index),一个是remove(Object o)
public E remove(int index) {
Objects.checkIndex(index, size);
final Object[] es = elementData;
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
fastRemove(es, index);
return oldValue;
}
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found: {
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
break found;
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;
}
return false;
}
fastRemove(es, i);
return true;
}
private void fastRemove(Object[] es, int i) {
modCount++;
final int newSize;
if ((newSize = size - 1) > i)
System.arraycopy(es, i + 1, es, i, newSize - i);
es[size = newSize] = null;
}
可以看到在remove(int index)当中会跟add(Object o , int index)一样先检查index是否越界,因为arraylist是非线程安全的,在多线程中可能存在同时新增或者删除的情况,所以需要先检查是否越界。remove(Object o )中可以看出删除的是第一个对象,同时也可以看出在新增的时候是可以新增null的。fastRemove主要是将数组的index+1到末尾copy到index到末尾。
iterator()
因为Arraylist实现了Iterator接口,所以也可以用迭代器访问
//返回了一个内部迭代器对象
public Iterator<E> iterator() {
return new Itr();
}
Itr
属性:
- cursor 下一个要返回的元素的索引,默认赋值0
- lastRet 最后一个返回元素的索引,-1表示没有值
- expectedModCount 期待的修改数
方法
- hasNext()
public boolean hasNext() {
//下一个值是否是数组大小,如果是就不能继续迭代
return cursor != size;
}
2.next()
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
//表示迭代期间集合被修改需要抛出异常
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
3.remove()
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
从迭代器代码中也可以看出arraylist非线程安全,考虑线程安全的话可以使用Collections.synchronizedList