转载请注明原文地址: http://zk-chs.iteye.com/blog/2250804
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
上面是是ArrayList类的定义,它继承了抽象类AbstractList,但是真正继承的方法只有equals和hashCode,
别的方法在ArrayList 中都有自己的重新实现;
List接口在AbstractList中已经实现,这里是为了表明一下,没有太大含义;
RandomAccess没有方法,表明ArrayList支持快速随机访问;
实 现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制,如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常;
类通过实现 java.io.Serializable 接口以启用其序列化功能,未实现此接口的类将无法使其任何状态序列化或反序列化
transient Object[] elementData; // 我们用于存储数据的数组 private static final int DEFAULT_CAPACITY = 10; // 默认大小为10 private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; private int size; // elementDate中对象数量,不是length protected transient int modCount = 0; // 用于并发使用 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); } } public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { this.elementData = EMPTY_ELEMENTDATA; } }EMPTY_ELEMENTDATA在使用带参数构造函数时使用; DEFAULTCAPACITY_EMPTY_ELEMENTDATA在使用默认构造函数时使用; DEFAULT_CAPACITY会在默认构造函数实例的第一次调用add方法时使用; modCount:当迭代时,如果modCount发生了变化,那么抛出并发修改异常(ConcurrentModificationException); 关于ArrayList的域就介绍这么多,下面看看方法: public boolean add(E e):
// 在当前列表末尾添加一个对象,而不是数组 public boolean add(E e) { // 确认数组大小,并让modCount + 1 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } // if判断用于第一次调用add,如果是使用无参构造函数,那么进入此方法,设置minCapacity为10 private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // first add minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } // modCount自增,并判断数组大小是否足够,不够的话将增大数组(下面介绍grow) private void ensureExplicitCapacity(int minCapacity) { modCount++; // 判断数组大小是否足够 if (minCapacity - elementData.length > 0) grow(minCapacity); }private void grow(int minCapacity):这是private方法,不能使用
private void grow(int minCapacity) { // 传入需要的数组大小 // oldCapacity为当前数组大小 int oldCapacity = elementData.length; // 设置新数组大小的值,为当前的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); // 当addAll时可能新数组大小也不够 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // newCapacity可能会溢出,这里做判断 if (newCapacity - MAX_ARRAY_SIZE > 0) // MAX_ARRAY_SIZE = 2147483639 newCapacity = hugeCapacity(minCapacity); // 使用Arrays扩展数组至newCapacity elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow 溢出 抛出异常 throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : //2147483647 MAX_ARRAY_SIZE; // 2147483639 }public boolean addAll(Collection<? extends E> c):
public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); // 传入集合的数组显示 int numNew = a.length; ensureCapacityInternal(size + numNew); // 同上 // 将a的numNew长度的元素添加到elementDate的末尾 System.arraycopy(a, 0, elementData, size, numNew); size += numNew; // 对象数量增长numNew return numNew != 0; // 如果c刚刚创建没有调用add,那么numNew会为0 }public void add(int index, E element) 和 public boolean addAll(int index, Collection<? extends E> c):
// 从指定索引位置插入元素 public void add(int index, E element) { rangeCheckForAdd(index); // 判断插入位置是否越界 // 和add没什么不同 ensureCapacityInternal(size + 1); // Increments modCount!! // 这就是我们常说的后移一位,其实是从指定位置开始复制 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } // 同上 public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); // 判断插入位置是否越界 Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } // 用于add和addAll 判断传入的索引值index是否越界 private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }需要注意:不管addAll添加多少元素,modCount只会自增1!!!
public E get(int index):
public E get(int index) { // 获取指定位置元素 rangeCheck(index); // 注意 这里不是rangeCheckForAdd,下面介绍 return elementData(index); }
public E set(int index, E element):
// 替换指定索引位置的元素,返回原位置元素 public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; }public E get(int index):
public E get(int index) { // 获取指定位置元素 rangeCheck(index); // 注意 这里不是rangeCheckForAdd,下面介绍 return elementData(index); }public E set(int index, E element): public E remove(int index): 已经申请的内存空间不会回收(删除指定索引位置元素)
public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); // 返回索引位置元素 int numMoved = size - index - 1; // 需要前移元素的数量 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); // 相当于index+1后的元素前移一位 elementData[--size] = null; // clear to let GC do its work 通知jvm回收,防止内存泄漏 return oldValue; // 返回从list中移除的元素 } // 这里仅与size比较,小于0数组本身会抛异常 private void rangeCheck(int index) { if (index >= size) // 防止index在size与elementDate.length之间 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } // 返回索引位置元素 E elementData(int index) { return (E) elementData[index]; }public boolean remove(Object o):(删除指定元素)
// 通过遍历数组删除指定元素 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); // 快速删除 return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } // 为什么叫fastRemove?因为不需要再做检查,后面与remove相同 private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }public void trimToSize():
// 将当前列表大小修改为当前元素size大小,释放被占用的空间 public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); // 复制size个元素,即数组大小变成size } }public int size() 和 public boolean isEmpty():
public int size() { return size; // 直接返回size } public boolean isEmpty() { return size == 0; }public boolean contains(Object o):
// 是否包含指定元素, public boolean contains(Object o) { return indexOf(o) >= 0; // indexOf下面介绍 }public int indexOf(Object o) 和 public int lastIndexOf(Object o):
/** * 一个从前向后遍历,一个从后向前遍历 */ public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; } public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; }public Object clone():
// 为浅拷贝,不会拷贝数组内元素,两个列表引用相同的元素 public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // 实现了Cloneable就不会出现 // this shouldn't happen, since we are Cloneable throw new InternalError(e); } }public Object[] toArray():
// 返回一个复制的数组,大小为size,而不是elementData.length,含有elementData中所有元素 public Object[] toArray() { return Arrays.copyOf(elementData, size); }public <T> T[] toArray(T[] a):
// 传入一个指定类型的数组 public <T> T[] toArray(T[] a) { if (a.length < size) // 如果a长度小于size,那么直接复制elementData,大小为size // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); // 否则从a的0索引开始复制,而且a[size]会被设置为null !!!!! // 如果你的数组很重要,那就小心点这个方法 System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }public void clear():
// 清空当前列表,但是已经申请的空间大小(elementData.length)不会变 public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }public void ensureCapacity(int minCapacity):
// 保证当前列表至少有minCapacity的大小 public void ensureCapacity(int minCapacity) { // minExpand为0或为10 int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }protected void removeRange(int fromIndex, int toIndex):
protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; // 要移动的元素数量 // 将从toIndex开始,共numMoved个元素移动到fromIndex的位置 System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // clear to let GC do its work // 移除范围内元素后新的size大小 int newSize = size - (toIndex-fromIndex); // 将复制的多余的数组空间设置为空,使gc可以回收,防止内存泄漏 for (int i = newSize; i < size; i++) { elementData[i] = null; } size = newSize; }public boolean removeAll(Collection<?> c) 和 public boolean retainAll(Collection<?> c):
// 删除所有与c中任一对象相同的对象,从下面到contains我们能知道是调用equals比较 public boolean removeAll(Collection<?> c) { // 判断是否为空,为空抛出空指针 Objects.requireNonNull(c); return batchRemove(c, false); } // 保留所有与c中任一对象相同的对象 public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); } // 批量删除,不建议使用,contains每次都要遍历,效率低下 private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) // contains每次都要遍历 if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. // finally语句块,即使contains抛出异常也会执行 if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; }
public List<E> subList(int fromIndex, int toIndex):
public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); // 常规的判断,见下 return new SubList(this, 0, fromIndex, toIndex); // 内部类SubList,后面介绍 } static void subListRangeCheck(int fromIndex, int toIndex, int size) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > size) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); }
public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); // 常规的判断,见下 return new SubList(this, 0, fromIndex, toIndex); // 内部类SubList,后面介绍 } static void subListRangeCheck(int fromIndex, int toIndex, int size) { if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); if (toIndex > size) throw new IndexOutOfBoundsException("toIndex = " + toIndex); if (fromIndex > toIndex) throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); }下面看看内部类SubList
private class SubList extends AbstractList<E> implements RandomAccess除了是private没什么特别的
// 接着是域和构造函数,传入的list作为parent引用的对象 private final AbstractList<E> parent; private final int parentOffset; private final int offset; int size; SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) { this.parent = parent; this.parentOffset = fromIndex; this.offset = offset + fromIndex; this.size = toIndex - fromIndex; // 截取的新列表的元素数量 this.modCount = ArrayList.this.modCount; }可以看到sublist的所有状态都是与传入的parent相关的; 如果你看了sublist的源码的话,你会发现它操作的就是parent的elementData数组; 只是每个方法添加了个offset而已,方法内容都是一样的,这里就不再重复了; ArrayList的迭代器有2种;分别是Itr和ListItr;
private class Itr implements Iterator<E> private class ListItr extends Itr implements ListIterator<E>List比Itr多了操作对象的方法(例如add,set,previous等等); 下面是调用迭代器的方法:
// ListIterator支持从指定索引开始迭代 public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } public ListIterator<E> listIterator() { return new ListItr(0); } public Iterator<E> iterator() { return new Itr(); }多看集合容器源码对于我们理解和使用容器是很有好处的,而且可以更好的在编写并发代码 并发处理一定要良好的运用各个集合容器,以及扩展的concurrent下的线程安全容器(并非一定安全) 如果仅仅使用像vector一样的全部方法synchronized的集合的话,那么效率会非常低; 跑题了,希望能够一起进步吧...