ArrayList
特点
数组实现,能够随机访问,增加和删除慢
实现
//默认初始容量:10
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
//elementData.length是实际的空间
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
//size是ArrayList的容量
private int size;
声明
默认构造函数
指定缓冲区为DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
带参构造函数
指定初始容量,更换缓冲区
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);
}
}
带集合参数构造函数
将集合对象转换为数组,更新ArrayList的size属性为集合对象的大小。
如果集合不为空:
- 判断传入的集合是否为ArrayList,如果是的话直接更改elementData的引用;
- 如果集合类不是ArrayList,通过Arrays.copyOf()进行扩容和复制。
如果集合为空,则将elementData初始化为EMPTY_ELEMENTDATA
public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray();
if ((size = a.length) != 0) {
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
压缩容量
当数组扩容后,就算删除了元素,elementData仍然是扩容之后的大小,只是size会改变。
为了减少ArrayList占用的空间,可以通过trimToSize将elementData的空间压缩到size的大小。
public void trimToSize() {
modCount++; //记录被修改的次数,带modCount的都是线程不安全?
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
是否包含某元素
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
/**
* Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index {@code i} such that
* or -1 if there is no such index.
*/
public int indexOf(Object o) {
return indexOfRange(o, 0, size);
}
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData;
if (o == null) {
for (int i = start; i < end; i++) {
if (es[i] == null) { //如果找null,用==判等
return i;
}
}
} else {
for (int i = start; i < end; i++) {
if (o.equals(es[i])) { //非空值则使用equals
return i;
}
}
}
return -1;
}
上述函数是寻找o第一次出现的索引,设计者提供了lastIndexOf()函数用于寻找最后出现的索引,本质上就是从elementData的末尾开始查找
获取元素
E elementData(int index) {
return (E) elementData[index];
}
@SuppressWarnings("unchecked")
static <E> E elementAt(Object[] es, int index) {
return (E) es[index];
}
/**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
/*
if (index < 0 || index >= length)
throw outOfBoundsCheckIndex(oobef, index, length);
*/
Objects.checkIndex(index, size);
return elementData(index);
}
删除元素
删除指定索引位置的元素
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;
}
private void fastRemove(Object[] es, int i) {
modCount++;
final int newSize;
//将i之后的newSize-i个元素复制到前面
if ((newSize = size - 1) > i)
System.arraycopy(es, i + 1, es, i, newSize - i);
es[size = newSize] = null;
}
删除指定值的元素
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
//寻找元素下标,调用私有的remove方法完成删除
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;
}
插入元素
public void add(int index, E element) {
//检查index是不是小于0或者大于size
rangeCheckForAdd(index);
modCount++;
final int s;
Object[] elementData;
//如果size的大小和elementData的长度一致,说明缓冲区已满
if ((s = size) == (elementData = this.elementData).length)
elementData = grow(); //扩容
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
elementData[index] = element; //更新缓冲区
size = s + 1; //更新size
}
private Object[] grow() {
return grow(size + 1);
}
扩容函数grow(minCapacity),并非直接扩容到minCapacity,而是通过ArraySupport.newLength()计算一个新的容量。
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)];
}
}
新的容量preLength=oldCapacity + Math.max(minCapacity - oldCapacity, oldCapacity/2),也就是最少增长oldCapacity/2 。
-
如果新的容量preLength < SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8,则是合法的容量。
-
如果新的容量 > SOFT_MAX_ARRAY_LENGTH,则需要调用hugeLength进行特殊处理:
- 如果oldCapacity + minGrowth < 0,说明溢出了,抛出异常;
- 如果oldCapacity + minGrowth < SOFT_MAX_ARRAY_LENGTH,返回 SOFT_MAX_ARRAY_LENGTH;
- 如果oldCapacity + minGrowth > SOFT_MAX_ARRAY_LENGTH,返回oldCapacity + minGrowth。
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// preconditions not checked because of inlining
// assert oldLength >= 0
// assert minGrowth > 0
int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow
if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
return prefLength;
} else {
// put code cold in a separate method
return hugeLength(oldLength, minGrowth);
}
}