Java的ArrayList源码浅析
2015-09-10 18:01
483 查看
public class ArrayList<E> extends AbstractList<E> implements Cloneable, Serializable, RandomAccess
Java在集合模块中提供的一个工具类,继承AbstractList抽象类,支持泛型。
本日志分析的源码来自android-22\java\util\ArrayList.java
ArrayList类内包含一个数组,并为其设置一个的长度,当数组的内容添加到某个设定长度时,将重新赋值一个长度更大的数组,并通过arraycopy方法把旧的内容克隆过去,从而实现动态可变的数据结构的策略,并提供插入、删除等方法。
一、该类包含4个域:
/**
* The elements in this list, followed by nulls.
*/
transient Object[] array;
解析:transient 关键字表示,当this对象被保存时(Serializable),array域除外。array数组该集合类内容的容器,数据的操作实质上是对array域的操作。该集合类只是对操作方法进行封装。
/**
* The number of elements in this list.
*/
int size;
解析:array域的数组长度
/**
* The minimum amount by which the capacity of an ArrayList will increase.
* This tuning parameter controls a time-space tradeoff. This value (12)
* gives empirically good results and is arguably consistent with the
* RI's specified default initial capacity of 10: instead of 10, we start
* with 0 (sans allocation) and jump to 12.
*/
private static final int MIN_CAPACITY_INCREMENT = 12;
解析:缺省值下,容器的默认长度
/**
* A counter for changes to the list.
*/
protected transient int modCount;
解析:AbstractList的域,记录调用操作方法的次数,用以避免并发调用产生的错误
[b]二、构造函数:[/b]
/**
* Constructs a new instance of {@code ArrayList} with the specified
* initial capacity.
*
* @param capacity
* the initial capacity of this {@code ArrayList}.
*/
public ArrayList(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException("capacity < 0: " + capacity);
}
array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);
}
解析: 构造并实例化array数组,当capacity==0时,创建一个空数组,否则创建长度为capacity的数组。
/**
* Constructs a new {@code ArrayList} instance with zero initial capacity.
*/
public ArrayList() {
array = EmptyArray.OBJECT;
}
解析:这是大多数情况,创建ArrayList对象时不输入参数,内部初始化直接创建一个空的array数组。
/**
* Constructs a new instance of {@code ArrayList} containing the elements of
* the specified collection.
*
* @param collection
* the collection of elements to add.
*/
public ArrayList(Collection<? extends E> collection) {
if (collection == null) {
throw new NullPointerException("collection == null");
}
Object[] a = collection.toArray();
if (a.getClass() != Object[].class) {
Object[] newArray = new Object[a.length];
System.arraycopy(a, 0, newArray, 0, a.length);
a = newArray;
}
array = a;
size = a.length;
}
解析:这个构造方法,入参所输入的集合,会直接加到新建的ArrayList对象的头部,成为新建对象的一部分。其中toArray()方法,在Collection接口中定义([b]AbstractList继承[b]Abstract[b]Collection[/b][/b],[b][b]Abstract[b]Collection[/b][/b]实现Collection[/b]),在ArrayList中实现toArray方法,是(创建新的数组并用arraycopy方法赋值一份副本后)直接返回ArrayList中的array数组。[/b]
[b]三、方法:[/b]
/**
* Adds the specified object at the end of this {@code ArrayList}.
*
* @param object
* the object to add.
* @return always true
*/
@Override public boolean add(E object) {
Object[] a = array;
int s = size;
if (s == a.length) {
Object[] newArray = new Object[s +
(s < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : s >> 1)];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
a[s] = object;
size = s + 1;
modCount++;
return true;
}
if(刚用第三个构造函数下创建ArrayList && 入参输入的集合不为空 == false), 在第一次调用add方法时size必定是0,同时a.length也是0,因此会创建newArray长度为默认值MIN_CAPACITY_INCERMENT的新数组,赋值给array,此时array的容量等于[b]MIN_CAPACITY_INCERMENT,把object赋值给a【0】(array = a),size+1=1。[/b]
else if (array中已有内容 && size == array.length) ,即array中的容量已塞满,将创建newArray,size小于[b][b]MIN_CAPACITY_INCERMENT/2,newArray的长度则为size+[b]MIN_CAPACITY_INCERMENT[/b],否则,newArray长度为size+size/2,后面arraycopy等略。[/b][/b]
[b][b] [/b]else , 即array不为空,未满,add方法的日常,直接把object赋值给array【size】,size++。[/b]
PS:array = [b]newArray,他们的长度就是ArrayList的容量,size是数组内容的长度,size小于等于容量。[/b]
@Override public boolean add(int index , E object)
同上面的的方法大同小异,在arraycopy是,先加index前面再加index后面,中间空一格出来,然后array【index】 = object。
/**
* This method controls the growth of ArrayList capacities. It represents
* a time-space tradeoff: we don't want to grow lists too frequently
* (which wastes time and fragments storage), but we don't want to waste
* too much space in unused excess capacity.
*
* NOTE: This method is inlined into {@link #add(Object)} for performance.
* If you change the method, change it there too!
*/
private static int newCapacity(int currentCapacity) {
int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
return currentCapacity + increment;
}
当ArrayList的内容批量增加(例如下面的方法,假设newPartSize这么多)时,不可避免要根据增加的长度来计算ArrayList应当增加[b](需要增加比[b]newPartSize多一点)[/b]的容量,这个方法就是用来干这个。当currentCapacity(=size+newPartSize)小于[b][b]MIN_CAPACITY_INCERMENT/2,即result
= [/b][/b]currentCapaci
fcdc
ty + MIN_CAPACITY_INCERMENT,否则[b][b][b]result[/b][/b]
=currentCapacity + currentCapacity/2,并返回[b][b]result[/b][/b]。[/b][/b]
/**
* Adds the objects in the specified collection to this {@code ArrayList}.
*
* @param collection
* the collection of objects.
* @return {@code true} if this {@code ArrayList} is modified, {@code false}
* otherwise.
*/
@Override public boolean addAll(Collection<? extends E> collection) {
Object[] newPart = collection.toArray();
int newPartSize = newPart.length;
if (newPartSize == 0) {
return false;
}
Object[] a = array;
int s = size;
int newSize = s + newPartSize; // If add overflows, arraycopy will fail
if (newSize > a.length) {
int newCapacity = newCapacity(newSize - 1); // ~33% growth room
Object[] newArray = new Object[newCapacity];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
System.arraycopy(newPart, 0, a, s, newPartSize);
size = newSize;
modCount++;
return true;
}
ArrayList的内容批量add,newSize如果大于容量的话,调用newCapacity方法获取新的容量长度,创建新的数组赋值改array,把旧的数据arraycopy过来。最后再把newPart arraycopy过去给array。
/**
* Inserts the objects in the specified collection at the specified location
* in this List. The objects are added in the order they are returned from
* the collection's iterator.
*
* @param index
* the index at which to insert.
* @param collection
* the collection of objects.
* @return {@code true} if this {@code ArrayList} is modified, {@code false}
* otherwise.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || location > size()}
*/
@Override
public boolean addAll(int index, Collection<? extends E> collection) {
int s = size;
if (index > s || index < 0) {
throwIndexOutOfBoundsException(index, s);
}
Object[] newPart = collection.toArray();
int newPartSize = newPart.length;
if (newPartSize == 0) {
return false;
}
Object[] a = array;
int newSize = s + newPartSize; // If add overflows, arraycopy will fail
if (newSize <= a.length) {
System.arraycopy(a, index, a, index + newPartSize, s - index);
} else {
int newCapacity = newCapacity(newSize - 1); // ~33% growth room
Object[] newArray = new Object[newCapacity];
System.arraycopy(a, 0, newArray, 0, index);
System.arraycopy(a, index, newArray, index + newPartSize, s-index);
array = a = newArray;
}
System.arraycopy(newPart, 0, a, index, newPartSize);
size = newSize;
modCount++;
return true;
}
ArrayList的内容批量add到index位置,插入。扩充容量和上面的方法一样,插入时先copy 原来0~index的内容到前面,再copy 原来index ~ s的内容到后面,newPart的内容copy到中间。
/**
* This method was extracted to encourage VM to inline callers.
* TODO: when we have a VM that can actually inline, move the test in here too!
*/
static IndexOutOfBoundsException throwIndexOutOfBoundsException(int index, int size) {
throw new IndexOutOfBoundsException("Invalid index " + index + ", size is " + size);
}
/**
* Removes all elements from this {@code ArrayList}, leaving it empty.
*
* @see #isEmpty
* @see #size
*/
@Override public void clear() {
if (size != 0) {
Arrays.fill(array, 0, size, null);
size = 0;
modCount++;
}
}
ArrayList调用clear方法, array数组中的内容全部填null,容量(数组所占空间)没有改变。
/**
* Returns a new {@code ArrayList} with the same elements, the same size and
* the same capacity as this {@code ArrayList}.
*
* @return a shallow copy of this {@code ArrayList}
* @see java.lang.Cloneable
*/
@Override public Object clone() {
try {
ArrayList<?> result = (ArrayList<?>) super.clone();
result.array = array.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
return a shallow copy。
/**
* Ensures that after this operation the {@code ArrayList} can hold the
* specified number of elements without further growing.
*
* @param minimumCapacity
* the minimum capacity asked for.
*/
public void ensureCapacity(int minimumCapacity) {
Object[] a = array;
if (a.length < minimumCapacity) {
Object[] newArray = new Object[minimumCapacity];
System.arraycopy(a, 0, newArray, 0, size);
array = newArray;
modCount++;
}
}
指定最小容量大小,当当前数组的大小(即容量)小于minimumCapacity时,重建array数组,大小为 [b]minimumCapacity,把旧数据copy过去。[/b]
@SuppressWarnings("unchecked") @Override public E get(int index) {
if (index >= size) {
throwIndexOutOfBoundsException(index, size);
}
return (E) array[index];
}
ArrayList的get方法,实际上是返回array数组的元素。
@SuppressWarnings("unchecked") 编译器对警告沉默(这里是强制装换)
/**
* Returns the number of elements in this {@code ArrayList}.
*
* @return the number of elements in this {@code ArrayList}.
*/
@Override public int size() {
return size;
}
返回长度,非容量(array.length)。
@Override public boolean isEmpty() {
return size == 0;
}
长度是否为0
/**
* Searches this {@code ArrayList} for the specified object.
*
* @param object
* the object to search for.
* @return {@code true} if {@code object} is an element of this
* {@code ArrayList}, {@code false} otherwise
*/
@Override public boolean contains(Object object) {
Object[] a = array;
int s = size;
if (object != null) {
for (int i = 0; i < s; i++) {
if (object.equals(a[i])) {
return true;
}
}
} else {
for (int i = 0; i < s; i++) {
if (a[i] == null) {
return true;
}
}
}
return false;
}
检测ArrayList中是否包含元素,对array数组遍历,从源码中看出,object入参可以输入null。
@Override public int indexOf(Object object) {
Object[] a = array;
int s = size;
if (object != null) {
for (int i = 0; i < s; i++) {
if (object.equals(a[i])) {
return i;
}
}
} else {
for (int i = 0; i < s; i++) {
if (a[i] == null) {
return i;
}
}
}
return -1;
}
检测ArrayList某元素的位置,从头部开始对array数组遍历,[b]object入参可以输入null。[/b]
@Override public int lastIndexOf(Object object) {
Object[] a = array;
if (object != null) {
for (int i = size - 1; i >= 0; i--) {
if (object.equals(a[i])) {
return i;
}
}
} else {
for (int i = size - 1; i >= 0; i--) {
if (a[i] == null) {
return i;
}
}
}
return -1;
}
检测ArrayList某元素的位置,从尾部开始对array数组遍历,[b]object入参可以输入null。[/b]
/**
* Removes the object at the specified location from this list.
*
* @param index
* the index of the object to remove.
* @return the removed object.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || location >= size()}
*/
@Override public E remove(int index) {
Object[] a = array;
int s = size;
if (index >= s) {
throwIndexOutOfBoundsException(index, s);
}
@SuppressWarnings("unchecked") E result = (E) a[index];
System.arraycopy(a, index + 1, a, index, --s - index);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return result;
}
删除arayList的index元素,把array的 index+1 ~ 尾部位置的内容,copy到自己的index ~ 尾部 -1的位置去,然后把尾部的元素赋值为null。
@Override public boolean remove(Object object) {
Object[] a = array;
int s = size;
if (object != null) {
for (int i = 0; i < s; i++) {
if (object.equals(a[i])) {
System.arraycopy(a, i + 1, a, i, --s - i);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return true;
}
}
} else {
for (int i = 0; i < s; i++) {
if (a[i] == null) {
System.arraycopy(a, i + 1, a, i, --s - i);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return true;
}
}
}
return false;
}
遍历array数组,找出object的位置,用remove(int index)的思路删除index位置的元素。
@Override protected void removeRange(int fromIndex, int toIndex) {
if (fromIndex == toIndex) {
return;
}
Object[] a = array;
int s = size;
if (fromIndex >= s) {
throw new IndexOutOfBoundsException("fromIndex " + fromIndex
+ " >= size " + size);
}
if (toIndex > s) {
throw new IndexOutOfBoundsException("toIndex " + toIndex
+ " > size " + size);
}
if (fromIndex > toIndex) {
throw new IndexOutOfBoundsException("fromIndex " + fromIndex
+ " > toIndex " + toIndex);
}
System.arraycopy(a, toIndex, a, fromIndex, s - toIndex);
int rangeSize = toIndex - fromIndex;
Arrays.fill(a, s - rangeSize, s, null);
size = s - rangeSize;
modCount++;
}
把array数组的 toindex[b] ~ 尾部位置的内容,copy到自己的 fromindex[b]
~ 尾部[/b]- (toindex[b] [/b]-[b]fromindex[/b])
的位置去,然后把尾部的元素全部赋值为null。[/b]
/**
* Replaces the element at the specified location in this {@code ArrayList}
* with the specified object.
*
* @param index
* the index at which to put the specified object.
* @param object
* the object to add.
* @return the previous element at the index.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || location >= size()}
*/
@Override public E set(int index, E object) {
Object[] a = array;
if (index >= size) {
throwIndexOutOfBoundsException(index, size);
}
@SuppressWarnings("unchecked") E result = (E) a[index];
a[index] = object;
return result;
}
把array数组的index位置的元素赋值为object。
/**
* Returns a new array containing all elements contained in this
* {@code ArrayList}.
*
* @return an array of the elements from this {@code ArrayList}
*/
@Override public Object[] toArray() {
int s = size;
Object[] result = new Object[s];
System.arraycopy(array, 0, result, 0, s);
return result;
}
[b]返回一份array的副本,返回的是数组。[/b]
/**
* Returns an array containing all elements contained in this
* {@code ArrayList}. If the specified array is large enough to hold the
* elements, the specified array is used, otherwise an array of the same
* type is created. If the specified array is used and is larger than this
* {@code ArrayList}, the array element following the collection elements
* is set to null.
*
* @param contents
* the array.
* @return an array of the elements from this {@code ArrayList}.
* @throws ArrayStoreException
* when the type of an element in this {@code ArrayList} cannot
* be stored in the type of the specified array.
*/
@Override public <T> T[] toArray(T[] contents) {
int s = size;
if (contents.length < s) {
@SuppressWarnings("unchecked") T[] newArray
= (T[]) Array.newInstance(contents.getClass().getComponentType(), s);
contents = newArray;
}
System.arraycopy(this.array, 0, contents, 0, s);
if (contents.length > s) {
contents[s] = null;
}
return contents;
}
[b] 输入一个数组contents,把array的内容copy进去,如果contents的长度小于array的内容长度(非array.length),则创建一个容量为array内容长度的newArray赋值给contents并返回。[/b]
/**
* Sets the capacity of this {@code ArrayList} to be the same as the current
* size.
*
* @see #size
*/
public void trimToSize() {
int s = size;
if (s == array.length) {
return;
}
if (s == 0) {
array = EmptyArray.OBJECT;
} else {
Object[] newArray = new Object[s];
System.arraycopy(array, 0, newArray, 0, s);
array = newArray;
}
modCount++;
}
把array的占[b]空间的长度,修剪成array的内容长度。[/b]
@Override public Iterator<E> iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator<E> {
/** Number of elements remaining in this iteration */
private int remaining = size;
/** Index of element that remove() would remove, or -1 if no such elt */
private int removalIndex = -1;
/** The expected modCount value */
private int expectedModCount = modCount;
public boolean hasNext() {
return remaining != 0;
}
@SuppressWarnings("unchecked") public E next() {
ArrayList<E> ourList = ArrayList.this;
int rem = remaining;
if (ourList.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (rem == 0) {
throw new NoSuchElementException();
}
remaining = rem - 1;
return (E) ourList.array[removalIndex = ourList.size - rem];
}
public void remove() {
Object[] a = array;
int removalIdx = removalIndex;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (removalIdx < 0) {
throw new IllegalStateException();
}
System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
a[--size] = null; // Prevent memory leak
removalIndex = -1;
expectedModCount = ++modCount;
}
}
[b] 调用iterator方法,返回一个ArrayList的迭代器。[/b]
@Override public int hashCode() {
Object[] a = array;
int hashCode = 1;
for (int i = 0, s = size; i < s; i++) {
Object e = a[i];
hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
}
return hashCode;
}
这里有返回hashCode的计算公式。
@Override public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof List)) {
return false;
}
List<?> that = (List<?>) o;
int s = size;
if (that.size() != s) {
return false;
}
Object[] a = array;
if (that instanceof RandomAccess) {
for (int i = 0; i < s; i++) {
Object eThis = a[i];
Object ethat = that.get(i);
if (eThis == null ? ethat != null : !eThis.equals(ethat)) {
return false;
}
}
} else { // Argument list is not random access; use its iterator
Iterator<?> it = that.iterator();
for (int i = 0; i < s; i++) {
Object eThis = a[i];
Object eThat = it.next();
if (eThis == null ? eThat != null : !eThis.equals(eThat)) {
return false;
}
}
}
return true;
}
private static final long serialVersionUID = 8683452581122892189L;
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeInt(array.length);
for (int i = 0; i < size; i++) {
stream.writeObject(array[i]);
}
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
int cap = stream.readInt();
if (cap < size) {
throw new InvalidObjectException(
"Capacity: " + cap + " < size: " + size);
}
array = (cap == 0 ? EmptyArray.OBJECT : new Object[cap]);
for (int i = 0; i < size; i++) {
array[i] = stream.readObject();
}
}
Java在集合模块中提供的一个工具类,继承AbstractList抽象类,支持泛型。
本日志分析的源码来自android-22\java\util\ArrayList.java
ArrayList类内包含一个数组,并为其设置一个的长度,当数组的内容添加到某个设定长度时,将重新赋值一个长度更大的数组,并通过arraycopy方法把旧的内容克隆过去,从而实现动态可变的数据结构的策略,并提供插入、删除等方法。
一、该类包含4个域:
/**
* The elements in this list, followed by nulls.
*/
transient Object[] array;
解析:transient 关键字表示,当this对象被保存时(Serializable),array域除外。array数组该集合类内容的容器,数据的操作实质上是对array域的操作。该集合类只是对操作方法进行封装。
/**
* The number of elements in this list.
*/
int size;
解析:array域的数组长度
/**
* The minimum amount by which the capacity of an ArrayList will increase.
* This tuning parameter controls a time-space tradeoff. This value (12)
* gives empirically good results and is arguably consistent with the
* RI's specified default initial capacity of 10: instead of 10, we start
* with 0 (sans allocation) and jump to 12.
*/
private static final int MIN_CAPACITY_INCREMENT = 12;
解析:缺省值下,容器的默认长度
/**
* A counter for changes to the list.
*/
protected transient int modCount;
解析:AbstractList的域,记录调用操作方法的次数,用以避免并发调用产生的错误
[b]二、构造函数:[/b]
/**
* Constructs a new instance of {@code ArrayList} with the specified
* initial capacity.
*
* @param capacity
* the initial capacity of this {@code ArrayList}.
*/
public ArrayList(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException("capacity < 0: " + capacity);
}
array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);
}
解析: 构造并实例化array数组,当capacity==0时,创建一个空数组,否则创建长度为capacity的数组。
/**
* Constructs a new {@code ArrayList} instance with zero initial capacity.
*/
public ArrayList() {
array = EmptyArray.OBJECT;
}
解析:这是大多数情况,创建ArrayList对象时不输入参数,内部初始化直接创建一个空的array数组。
/**
* Constructs a new instance of {@code ArrayList} containing the elements of
* the specified collection.
*
* @param collection
* the collection of elements to add.
*/
public ArrayList(Collection<? extends E> collection) {
if (collection == null) {
throw new NullPointerException("collection == null");
}
Object[] a = collection.toArray();
if (a.getClass() != Object[].class) {
Object[] newArray = new Object[a.length];
System.arraycopy(a, 0, newArray, 0, a.length);
a = newArray;
}
array = a;
size = a.length;
}
解析:这个构造方法,入参所输入的集合,会直接加到新建的ArrayList对象的头部,成为新建对象的一部分。其中toArray()方法,在Collection接口中定义([b]AbstractList继承[b]Abstract[b]Collection[/b][/b],[b][b]Abstract[b]Collection[/b][/b]实现Collection[/b]),在ArrayList中实现toArray方法,是(创建新的数组并用arraycopy方法赋值一份副本后)直接返回ArrayList中的array数组。[/b]
[b]三、方法:[/b]
/**
* Adds the specified object at the end of this {@code ArrayList}.
*
* @param object
* the object to add.
* @return always true
*/
@Override public boolean add(E object) {
Object[] a = array;
int s = size;
if (s == a.length) {
Object[] newArray = new Object[s +
(s < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : s >> 1)];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
a[s] = object;
size = s + 1;
modCount++;
return true;
}
if(刚用第三个构造函数下创建ArrayList && 入参输入的集合不为空 == false), 在第一次调用add方法时size必定是0,同时a.length也是0,因此会创建newArray长度为默认值MIN_CAPACITY_INCERMENT的新数组,赋值给array,此时array的容量等于[b]MIN_CAPACITY_INCERMENT,把object赋值给a【0】(array = a),size+1=1。[/b]
else if (array中已有内容 && size == array.length) ,即array中的容量已塞满,将创建newArray,size小于[b][b]MIN_CAPACITY_INCERMENT/2,newArray的长度则为size+[b]MIN_CAPACITY_INCERMENT[/b],否则,newArray长度为size+size/2,后面arraycopy等略。[/b][/b]
[b][b] [/b]else , 即array不为空,未满,add方法的日常,直接把object赋值给array【size】,size++。[/b]
PS:array = [b]newArray,他们的长度就是ArrayList的容量,size是数组内容的长度,size小于等于容量。[/b]
@Override public boolean add(int index , E object)
同上面的的方法大同小异,在arraycopy是,先加index前面再加index后面,中间空一格出来,然后array【index】 = object。
/**
* This method controls the growth of ArrayList capacities. It represents
* a time-space tradeoff: we don't want to grow lists too frequently
* (which wastes time and fragments storage), but we don't want to waste
* too much space in unused excess capacity.
*
* NOTE: This method is inlined into {@link #add(Object)} for performance.
* If you change the method, change it there too!
*/
private static int newCapacity(int currentCapacity) {
int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
return currentCapacity + increment;
}
当ArrayList的内容批量增加(例如下面的方法,假设newPartSize这么多)时,不可避免要根据增加的长度来计算ArrayList应当增加[b](需要增加比[b]newPartSize多一点)[/b]的容量,这个方法就是用来干这个。当currentCapacity(=size+newPartSize)小于[b][b]MIN_CAPACITY_INCERMENT/2,即result
= [/b][/b]currentCapaci
fcdc
ty + MIN_CAPACITY_INCERMENT,否则[b][b][b]result[/b][/b]
=currentCapacity + currentCapacity/2,并返回[b][b]result[/b][/b]。[/b][/b]
/**
* Adds the objects in the specified collection to this {@code ArrayList}.
*
* @param collection
* the collection of objects.
* @return {@code true} if this {@code ArrayList} is modified, {@code false}
* otherwise.
*/
@Override public boolean addAll(Collection<? extends E> collection) {
Object[] newPart = collection.toArray();
int newPartSize = newPart.length;
if (newPartSize == 0) {
return false;
}
Object[] a = array;
int s = size;
int newSize = s + newPartSize; // If add overflows, arraycopy will fail
if (newSize > a.length) {
int newCapacity = newCapacity(newSize - 1); // ~33% growth room
Object[] newArray = new Object[newCapacity];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
System.arraycopy(newPart, 0, a, s, newPartSize);
size = newSize;
modCount++;
return true;
}
ArrayList的内容批量add,newSize如果大于容量的话,调用newCapacity方法获取新的容量长度,创建新的数组赋值改array,把旧的数据arraycopy过来。最后再把newPart arraycopy过去给array。
/**
* Inserts the objects in the specified collection at the specified location
* in this List. The objects are added in the order they are returned from
* the collection's iterator.
*
* @param index
* the index at which to insert.
* @param collection
* the collection of objects.
* @return {@code true} if this {@code ArrayList} is modified, {@code false}
* otherwise.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || location > size()}
*/
@Override
public boolean addAll(int index, Collection<? extends E> collection) {
int s = size;
if (index > s || index < 0) {
throwIndexOutOfBoundsException(index, s);
}
Object[] newPart = collection.toArray();
int newPartSize = newPart.length;
if (newPartSize == 0) {
return false;
}
Object[] a = array;
int newSize = s + newPartSize; // If add overflows, arraycopy will fail
if (newSize <= a.length) {
System.arraycopy(a, index, a, index + newPartSize, s - index);
} else {
int newCapacity = newCapacity(newSize - 1); // ~33% growth room
Object[] newArray = new Object[newCapacity];
System.arraycopy(a, 0, newArray, 0, index);
System.arraycopy(a, index, newArray, index + newPartSize, s-index);
array = a = newArray;
}
System.arraycopy(newPart, 0, a, index, newPartSize);
size = newSize;
modCount++;
return true;
}
ArrayList的内容批量add到index位置,插入。扩充容量和上面的方法一样,插入时先copy 原来0~index的内容到前面,再copy 原来index ~ s的内容到后面,newPart的内容copy到中间。
/**
* This method was extracted to encourage VM to inline callers.
* TODO: when we have a VM that can actually inline, move the test in here too!
*/
static IndexOutOfBoundsException throwIndexOutOfBoundsException(int index, int size) {
throw new IndexOutOfBoundsException("Invalid index " + index + ", size is " + size);
}
/**
* Removes all elements from this {@code ArrayList}, leaving it empty.
*
* @see #isEmpty
* @see #size
*/
@Override public void clear() {
if (size != 0) {
Arrays.fill(array, 0, size, null);
size = 0;
modCount++;
}
}
ArrayList调用clear方法, array数组中的内容全部填null,容量(数组所占空间)没有改变。
/**
* Returns a new {@code ArrayList} with the same elements, the same size and
* the same capacity as this {@code ArrayList}.
*
* @return a shallow copy of this {@code ArrayList}
* @see java.lang.Cloneable
*/
@Override public Object clone() {
try {
ArrayList<?> result = (ArrayList<?>) super.clone();
result.array = array.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
return a shallow copy。
/**
* Ensures that after this operation the {@code ArrayList} can hold the
* specified number of elements without further growing.
*
* @param minimumCapacity
* the minimum capacity asked for.
*/
public void ensureCapacity(int minimumCapacity) {
Object[] a = array;
if (a.length < minimumCapacity) {
Object[] newArray = new Object[minimumCapacity];
System.arraycopy(a, 0, newArray, 0, size);
array = newArray;
modCount++;
}
}
指定最小容量大小,当当前数组的大小(即容量)小于minimumCapacity时,重建array数组,大小为 [b]minimumCapacity,把旧数据copy过去。[/b]
@SuppressWarnings("unchecked") @Override public E get(int index) {
if (index >= size) {
throwIndexOutOfBoundsException(index, size);
}
return (E) array[index];
}
ArrayList的get方法,实际上是返回array数组的元素。
@SuppressWarnings("unchecked") 编译器对警告沉默(这里是强制装换)
/**
* Returns the number of elements in this {@code ArrayList}.
*
* @return the number of elements in this {@code ArrayList}.
*/
@Override public int size() {
return size;
}
返回长度,非容量(array.length)。
@Override public boolean isEmpty() {
return size == 0;
}
长度是否为0
/**
* Searches this {@code ArrayList} for the specified object.
*
* @param object
* the object to search for.
* @return {@code true} if {@code object} is an element of this
* {@code ArrayList}, {@code false} otherwise
*/
@Override public boolean contains(Object object) {
Object[] a = array;
int s = size;
if (object != null) {
for (int i = 0; i < s; i++) {
if (object.equals(a[i])) {
return true;
}
}
} else {
for (int i = 0; i < s; i++) {
if (a[i] == null) {
return true;
}
}
}
return false;
}
检测ArrayList中是否包含元素,对array数组遍历,从源码中看出,object入参可以输入null。
@Override public int indexOf(Object object) {
Object[] a = array;
int s = size;
if (object != null) {
for (int i = 0; i < s; i++) {
if (object.equals(a[i])) {
return i;
}
}
} else {
for (int i = 0; i < s; i++) {
if (a[i] == null) {
return i;
}
}
}
return -1;
}
检测ArrayList某元素的位置,从头部开始对array数组遍历,[b]object入参可以输入null。[/b]
@Override public int lastIndexOf(Object object) {
Object[] a = array;
if (object != null) {
for (int i = size - 1; i >= 0; i--) {
if (object.equals(a[i])) {
return i;
}
}
} else {
for (int i = size - 1; i >= 0; i--) {
if (a[i] == null) {
return i;
}
}
}
return -1;
}
检测ArrayList某元素的位置,从尾部开始对array数组遍历,[b]object入参可以输入null。[/b]
/**
* Removes the object at the specified location from this list.
*
* @param index
* the index of the object to remove.
* @return the removed object.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || location >= size()}
*/
@Override public E remove(int index) {
Object[] a = array;
int s = size;
if (index >= s) {
throwIndexOutOfBoundsException(index, s);
}
@SuppressWarnings("unchecked") E result = (E) a[index];
System.arraycopy(a, index + 1, a, index, --s - index);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return result;
}
删除arayList的index元素,把array的 index+1 ~ 尾部位置的内容,copy到自己的index ~ 尾部 -1的位置去,然后把尾部的元素赋值为null。
@Override public boolean remove(Object object) {
Object[] a = array;
int s = size;
if (object != null) {
for (int i = 0; i < s; i++) {
if (object.equals(a[i])) {
System.arraycopy(a, i + 1, a, i, --s - i);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return true;
}
}
} else {
for (int i = 0; i < s; i++) {
if (a[i] == null) {
System.arraycopy(a, i + 1, a, i, --s - i);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return true;
}
}
}
return false;
}
遍历array数组,找出object的位置,用remove(int index)的思路删除index位置的元素。
@Override protected void removeRange(int fromIndex, int toIndex) {
if (fromIndex == toIndex) {
return;
}
Object[] a = array;
int s = size;
if (fromIndex >= s) {
throw new IndexOutOfBoundsException("fromIndex " + fromIndex
+ " >= size " + size);
}
if (toIndex > s) {
throw new IndexOutOfBoundsException("toIndex " + toIndex
+ " > size " + size);
}
if (fromIndex > toIndex) {
throw new IndexOutOfBoundsException("fromIndex " + fromIndex
+ " > toIndex " + toIndex);
}
System.arraycopy(a, toIndex, a, fromIndex, s - toIndex);
int rangeSize = toIndex - fromIndex;
Arrays.fill(a, s - rangeSize, s, null);
size = s - rangeSize;
modCount++;
}
把array数组的 toindex[b] ~ 尾部位置的内容,copy到自己的 fromindex[b]
~ 尾部[/b]- (toindex[b] [/b]-[b]fromindex[/b])
的位置去,然后把尾部的元素全部赋值为null。[/b]
/**
* Replaces the element at the specified location in this {@code ArrayList}
* with the specified object.
*
* @param index
* the index at which to put the specified object.
* @param object
* the object to add.
* @return the previous element at the index.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || location >= size()}
*/
@Override public E set(int index, E object) {
Object[] a = array;
if (index >= size) {
throwIndexOutOfBoundsException(index, size);
}
@SuppressWarnings("unchecked") E result = (E) a[index];
a[index] = object;
return result;
}
把array数组的index位置的元素赋值为object。
/**
* Returns a new array containing all elements contained in this
* {@code ArrayList}.
*
* @return an array of the elements from this {@code ArrayList}
*/
@Override public Object[] toArray() {
int s = size;
Object[] result = new Object[s];
System.arraycopy(array, 0, result, 0, s);
return result;
}
[b]返回一份array的副本,返回的是数组。[/b]
/**
* Returns an array containing all elements contained in this
* {@code ArrayList}. If the specified array is large enough to hold the
* elements, the specified array is used, otherwise an array of the same
* type is created. If the specified array is used and is larger than this
* {@code ArrayList}, the array element following the collection elements
* is set to null.
*
* @param contents
* the array.
* @return an array of the elements from this {@code ArrayList}.
* @throws ArrayStoreException
* when the type of an element in this {@code ArrayList} cannot
* be stored in the type of the specified array.
*/
@Override public <T> T[] toArray(T[] contents) {
int s = size;
if (contents.length < s) {
@SuppressWarnings("unchecked") T[] newArray
= (T[]) Array.newInstance(contents.getClass().getComponentType(), s);
contents = newArray;
}
System.arraycopy(this.array, 0, contents, 0, s);
if (contents.length > s) {
contents[s] = null;
}
return contents;
}
[b] 输入一个数组contents,把array的内容copy进去,如果contents的长度小于array的内容长度(非array.length),则创建一个容量为array内容长度的newArray赋值给contents并返回。[/b]
/**
* Sets the capacity of this {@code ArrayList} to be the same as the current
* size.
*
* @see #size
*/
public void trimToSize() {
int s = size;
if (s == array.length) {
return;
}
if (s == 0) {
array = EmptyArray.OBJECT;
} else {
Object[] newArray = new Object[s];
System.arraycopy(array, 0, newArray, 0, s);
array = newArray;
}
modCount++;
}
把array的占[b]空间的长度,修剪成array的内容长度。[/b]
@Override public Iterator<E> iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator<E> {
/** Number of elements remaining in this iteration */
private int remaining = size;
/** Index of element that remove() would remove, or -1 if no such elt */
private int removalIndex = -1;
/** The expected modCount value */
private int expectedModCount = modCount;
public boolean hasNext() {
return remaining != 0;
}
@SuppressWarnings("unchecked") public E next() {
ArrayList<E> ourList = ArrayList.this;
int rem = remaining;
if (ourList.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (rem == 0) {
throw new NoSuchElementException();
}
remaining = rem - 1;
return (E) ourList.array[removalIndex = ourList.size - rem];
}
public void remove() {
Object[] a = array;
int removalIdx = removalIndex;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (removalIdx < 0) {
throw new IllegalStateException();
}
System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
a[--size] = null; // Prevent memory leak
removalIndex = -1;
expectedModCount = ++modCount;
}
}
[b] 调用iterator方法,返回一个ArrayList的迭代器。[/b]
@Override public int hashCode() {
Object[] a = array;
int hashCode = 1;
for (int i = 0, s = size; i < s; i++) {
Object e = a[i];
hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
}
return hashCode;
}
这里有返回hashCode的计算公式。
@Override public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof List)) {
return false;
}
List<?> that = (List<?>) o;
int s = size;
if (that.size() != s) {
return false;
}
Object[] a = array;
if (that instanceof RandomAccess) {
for (int i = 0; i < s; i++) {
Object eThis = a[i];
Object ethat = that.get(i);
if (eThis == null ? ethat != null : !eThis.equals(ethat)) {
return false;
}
}
} else { // Argument list is not random access; use its iterator
Iterator<?> it = that.iterator();
for (int i = 0; i < s; i++) {
Object eThis = a[i];
Object eThat = it.next();
if (eThis == null ? eThat != null : !eThis.equals(eThat)) {
return false;
}
}
}
return true;
}
private static final long serialVersionUID = 8683452581122892189L;
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeInt(array.length);
for (int i = 0; i < size; i++) {
stream.writeObject(array[i]);
}
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
int cap = stream.readInt();
if (cap < size) {
throw new InvalidObjectException(
"Capacity: " + cap + " < size: " + size);
}
array = (cap == 0 ? EmptyArray.OBJECT : new Object[cap]);
for (int i = 0; i < size; i++) {
array[i] = stream.readObject();
}
}
相关文章推荐
- Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法
- java验证一个数是2的次幂
- Java CheckException与UncheckException
- spring容器创建对象的生命周期
- 【Spring】Spring MVC 的json问题(406 Not Acceptable)
- Maven Struts2
- struts2的获取请求方法
- Java访问权限修饰词
- java中thread的start()和run()的区别
- Java 集合 使用contains方法
- JAVA线程
- 初识 Struts1.x
- 关于JAVA IO流中拷贝文件的几种方法
- Eclipse下svn的创建分支/合并/切换使用
- Java中getResourceAsStream的用法
- java文件上传到服务器
- Spring MVC在接收复杂集合参数
- Struts2常用标签总结
- Java中Runnable和Thread的区别
- SpringMVC 3.0 常用注解简介