privatevoidfastRemove(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 }
privatebooleanbatchRemove(Collection<?> c, boolean complement){ final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. 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; }
只有中间插入时需要移位,先arraycopy挪出index位置,再把新数据填上
ArrayList.java
1 2 3 4 5 6 7 8 9
publicvoidadd(int index, E element){ rangeCheckForAdd(index);
publicintindexOf(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; }
publicintlastIndexOf(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; }
子列问题
ArrayList的子列并不再是ArrayList,而是单独定制的SubList
ArrayList.java
1 2 3 4
public List<E> subList(int fromIndex, int toIndex){ subListRangeCheck(fromIndex, toIndex, size); returnnew SubList(this, 0, fromIndex, toIndex); }
public Object[] toArray() { return Arrays.copyOf(elementData, size); }
可以传入一个数组来告知类型
如果传入的数组容量不够,那么就会生成一个新数组,这样返回的数组和传入的就不是一个
如果传入的数组容量超了,那么剩余的就会置null
最佳方式是传入一个和List一样大小的数组,这样可以避免内存浪费
ArrayList.java
1 2 3 4 5 6 7 8 9
public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }