diff --git a/second/week_01/36/ArrayList.md b/second/week_01/36/ArrayList.md new file mode 100644 index 0000000000000000000000000000000000000000..455391c005e4088bd1d52fac916984bdf5d8390d --- /dev/null +++ b/second/week_01/36/ArrayList.md @@ -0,0 +1,1002 @@ + +# ArrayList -- 查找快。 + + +# 1.继承关系: +``` java + public class ArrayList extends AbstractList + implements List, RandomAccess, Cloneable, java.io.Serializable +``` + +# 2. 属性: +``` java + // 默认容量 + private static final int DEFAULT_CAPACITY = 10; + + // 空数组,第一次存入元素时更新大小为 DEFAULT_CAPACITY + private static final Object[] EMPTY_ELEMENTDATA = {}; + + // 空数组,默认设定大小为 DEFAULT_CAPACITY + private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; + + // 添加第一个元素时扩展到默认容量,transient:关闭序列化 + transient Object[] elementData; + + // 数组中元素个数 + private int size; +``` + +# 3.方法: + +``` java + // 构造函数:initialCapacity 集合容量,该值为0时设定集合为 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); + } + } + + // 无参构造:默认设定大小为 DEFAULT_CAPACITY + public ArrayList() { + this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; + } + + // 构造函数:拷贝已知集合,若参数为空集合则使用 EMPTY_ELEMENTDATA。 + public ArrayList(Collection c) { + elementData = c.toArray(); + if ((size = elementData.length) != 0) { + // c.toArray might (incorrectly) not return Object[] (see 6260652) + if (elementData.getClass() != Object[].class) + elementData = Arrays.copyOf(elementData, size, Object[].class); + } else { + // replace with empty array. + this.elementData = EMPTY_ELEMENTDATA; + } + } + + // 将容量调整为数组的当前大小,可以最小化存储空间。 + public void trimToSize() { + modCount++; + if (size < elementData.length) { + elementData = (size == 0) + ? EMPTY_ELEMENTDATA + : Arrays.copyOf(elementData, size); + } + } + + // 增加此实例的容量,minCapacity 所需的最小容量 + public void ensureCapacity(int minCapacity) { + 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 ensureCapacityInternal(int minCapacity) { + if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { + minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); + } + ensureExplicitCapacity(minCapacity); + } + + private void ensureExplicitCapacity(int minCapacity) { + modCount++; + // overflow-conscious code + if (minCapacity - elementData.length > 0) + grow(minCapacity); + } + + // 数组最大容量(分配过大容量可能会导致 OOM 异常,因为超过了虚拟机限制) + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + // 增加容量到可以容纳 minCapacity 个元素。 + private void grow(int minCapacity) { + // overflow-conscious code + int oldCapacity = elementData.length; + int newCapacity = oldCapacity + (oldCapacity >> 1); + if (newCapacity - minCapacity < 0) + newCapacity = minCapacity; + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); + // minCapacity is usually close to size, so this is a win: + 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 : + MAX_ARRAY_SIZE; + } + + // 返回集合元素个数 + public int size() { + return size; + } + + // 检查是否为空 + public boolean isEmpty() { + return size == 0; + } + + // 检查是否存在元素: o + public boolean contains(Object o) { + return indexOf(o) >= 0; + } + + // 返回指定元素第一次出现的索引,无则返回 -1 。 + 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; + } + + // 返回指定元素最后一次出现的索引,无则返回 -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; + } + + // 浅clone,不会复制元素本身。 + public Object clone() { + try { + ArrayList v = (ArrayList) super.clone(); + v.elementData = Arrays.copyOf(elementData, size); + v.modCount = 0; + return v; + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(e); + } + } + + // 返回包含所有元素的数组,该数组是安全的。(此方法分配的是一个全新的数组,没有对它的引用存在,故调用者可对其自由修改。) + public Object[] toArray() { + return Arrays.copyOf(elementData, size); + } + + // 拷贝原集合元素到指定数组。 + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + if (a.length < size) + // 建一个 a 类型的新数组, 并填充当前集合的元素到其中。 + return (T[]) Arrays.copyOf(elementData, size, a.getClass()); + System.arraycopy(elementData, 0, a, 0, size); + if (a.length > size) + a[size] = null; + return a; + } + + // 返回对应索引位的元素 + @SuppressWarnings("unchecked") + E elementData(int index) { + return (E) elementData[index]; + } + + // 返回对应索引位的元素,提供对外访问,调用上一方法。 + public E get(int index) { + rangeCheck(index); + return elementData(index); + } + + // 替换对应索引位的元素 + public E set(int index, E element) { + rangeCheck(index); + + E oldValue = elementData(index); + elementData[index] = element; + return oldValue; + } + + // 于末尾新增指定元素 + public boolean add(E e) { + ensureCapacityInternal(size + 1); // Increments modCount!! + elementData[size++] = e; + return true; + } + + // 指定索引位插入式新增 + public void add(int index, E element) { + rangeCheckForAdd(index); + + ensureCapacityInternal(size + 1); // Increments modCount!! + System.arraycopy(elementData, index, elementData, index + 1, + size - index); + elementData[index] = element; + size++; + } + + // 移除对应索引位元素 + 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); + elementData[--size] = null; // clear to let GC do its work + + return oldValue; + } + + // 删除第一个匹配指定元素的元素,若不存在匹配元素则不变。 + 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; + } + + // 快速删除:跳过边界检查,且无返回 + 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 clear() { + modCount++; + + // clear to let GC do its work + for (int i = 0; i < size; i++) + elementData[i] = null; + + size = 0; + } + + // 追加指定非空集合所有元素到本集合末尾 + public boolean addAll(Collection c) { + Object[] a = c.toArray(); + int numNew = a.length; + ensureCapacityInternal(size + numNew); // Increments modCount + System.arraycopy(a, 0, elementData, size, numNew); + size += numNew; + return numNew != 0; + } + + // 从指定位置开始插入指定非空集合中的所有元素 + public boolean addAll(int index, Collection 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; + } + + // 删除介于指定索引位之间的元素 + protected void removeRange(int fromIndex, int toIndex) { + modCount++; + int numMoved = size - toIndex; + System.arraycopy(elementData, toIndex, elementData, fromIndex, + numMoved); + + // clear to let GC do its work + int newSize = size - (toIndex-fromIndex); + for (int i = newSize; i < size; i++) { + elementData[i] = null; + } + size = newSize; + } + + // 检查指定索引位是否大于集合总容量,此方法在访问数组元素前使用。 + private void rangeCheck(int index) { + if (index >= size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + // add 和 addAll使用的 rangeCheck 版本 + private void rangeCheckForAdd(int index) { + if (index > size || index < 0) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + // 构造索引越界(下标越界)的返回信息内容:索引值 + 集合总容量大小。 + private String outOfBoundsMsg(int index) { + return "Index: "+index+", Size: "+size; + } + + // 删除指定集合中的所有元素 + public boolean removeAll(Collection c) { + Objects.requireNonNull(c); + return batchRemove(c, false); + } + + // 仅保留指定集合中的元素,删除其余元素。 + public boolean retainAll(Collection c) { + Objects.requireNonNull(c); + return batchRemove(c, true); + } + + 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++) + 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; + } + + // 保存到流,即:序列化。 + private void writeObject(java.io.ObjectOutputStream s) + throws java.io.IOException{ + // Write out element count, and any hidden stuff + int expectedModCount = modCount; + s.defaultWriteObject(); + + // Write out size as capacity for behavioural compatibility with clone() + s.writeInt(size); + + // Write out all elements in the proper order. + for (int i=0; i