From 79f9f24bb2594628e47fff508397766657aa0c7d Mon Sep 17 00:00:00 2001 From: Air3 Date: Fri, 6 Mar 2020 19:40:52 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E5=91=A8:1,ArrayList,Lin?= =?UTF-8?q?kedList,HashMap=E6=BA=90=E7=A0=81=E5=88=86=E6=9E=90.=202020-03-?= =?UTF-8?q?06;1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...20\347\240\201\345\210\206\346\236\220.md" | 510 ++++++++++++++++++ ...20\347\240\201\345\210\206\346\236\220.md" | 175 ++++++ ...20\347\240\201\345\210\206\346\236\220.md" | 124 +++++ 3 files changed, 809 insertions(+) create mode 100644 "second/week_01/85/ArrayList \346\272\220\347\240\201\345\210\206\346\236\220.md" create mode 100644 "second/week_01/85/HashMap\346\272\220\347\240\201\345\210\206\346\236\220.md" create mode 100644 "second/week_01/85/LinkedList\346\272\220\347\240\201\345\210\206\346\236\220.md" diff --git "a/second/week_01/85/ArrayList \346\272\220\347\240\201\345\210\206\346\236\220.md" "b/second/week_01/85/ArrayList \346\272\220\347\240\201\345\210\206\346\236\220.md" new file mode 100644 index 0000000..7fc96d7 --- /dev/null +++ "b/second/week_01/85/ArrayList \346\272\220\347\240\201\345\210\206\346\236\220.md" @@ -0,0 +1,510 @@ +#ArrayList 源码分析 + +##总结: + 1,底层数组,基本是数组的特性,扩容随机访问,查询快,增删慢. + +##代码分析: + +1, +```代码注释: + extends AbstractList 继承抽象类 + implements List 实现了集合接口 + , RandomAccess 随机访问接口 + , Cloneable 克隆接口 + , java.io.Serializable 序列化接口 +``` + public class ArrayList extends AbstractList + implements List, RandomAccess, Cloneable, java.io.Serializable + { + private static final long serialVersionUID = 8683452581122892189L; + +2, +```代码注释: + 默认初始容量 +``` + private static final int DEFAULT_CAPACITY = 10; + +3, +```代码注释: + 空数组,用来置空 +``` + private static final Object[] EMPTY_ELEMENTDATA = {}; + +4, +```代码注释: + 默认空数组,用来置空 +``` + private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; + +5, +```代码注释: + 瞬态元素数组(ArrayList的本质数组)是default类型,并不是public公开的 +``` + transient Object[] elementData; // non-private to simplify nested class access + +6, +```代码注释: + 数组大小,也就是实际存储的元素个数 +``` + private int size; + +7, +```代码注释: + 带集合初始容量的构造方法 + <0 抛异常 +``` + 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); + } + } + +8, +```代码注释: + Collection 集合(泛型是继承自E) + + 将集合拷贝到数组中,用的是arrays的静态方法(用的是system的本地方法) + +``` + 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; + } + } + +8, +```代码注释: + 将数组两边删除为空的(未存储数据的部分),缩减为size大小的容量 +``` + public void trimToSize() { + + ** modCount是抽象方法中的属性,修改次数(modifyCount)** + modCount++; + if (size < elementData.length) { + elementData = (size == 0) + ? EMPTY_ELEMENTDATA + : Arrays.copyOf(elementData, size); + } + } + +8, +```代码注释: + 确认是否有最小容量的地方 +``` + 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 static int calculateCapacity(Object[] elementData, int minCapacity) { + if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { + return Math.max(DEFAULT_CAPACITY, minCapacity); + } + return minCapacity; + } + + private void ensureCapacityInternal(int minCapacity) { + ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); + } + + private void ensureExplicitCapacity(int minCapacity) { + modCount++; + + // overflow-conscious code + if (minCapacity - elementData.length > 0) + grow(minCapacity); + } + +8, +```代码注释: + 127-8=119,最大容量大小,之后会扩容 +``` + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + +8, +```代码注释: +扩容 +``` + 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; + } + + public boolean contains(Object o) { + return indexOf(o) >= 0; + } + +8, +```代码注释: + 从前查找对象,返回索引。 +``` + 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; + } + + 8, + ```代码注释: + 从后查找对象,返回索引。 + ``` + 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; + } + +8, +```代码注释: + 集合自身克隆,复制一份相同的 +``` + 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); + } + } + +8, +```代码注释: + 将集合转换为数组 +``` + public Object[] toArray() { + return Arrays.copyOf(elementData, size); + } + + + @SuppressWarnings("unchecked") + public 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; + } + + + + + 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++) + //null 用==判空 + if (elementData[index] == null) { + fastRemove(index); + return true; + } + } else { + for (int index = 0; index < size; index++) + //对象用.equals + if (o.equals(elementData[index])) { + fastRemove(index); + return true; + } + } + return false; + } + + + private void fastRemove(int index) { + //修改次数+1 + 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)); + } + + + 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 + + //参照cas自旋锁,先存修改次数, + 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