(源码分析)JDK1.8 ArrayList源码分析 布满荆棘的人生 2021-11-09 01:44 444阅读 0赞 ### 目录 ### * ArrayList的特点 * * 成员变量 * 构造方法 * add(E e) * add(int index, E element) * addAll(Collection<? extends E> c) * addAll(int index, Collection<? extends E> c) * remove(int index) * remove(Object o) * removeAll(Collection<?> c) * retainAll(Collection<?> c) * get(int index) * set(int index, E element) * clear() * contains(Object o) * isEmpty() * trimToSize() * size() * indexOf(Object o) * lastIndexOf(Object o) * clone() * toArray() * toArray(T\[\] a) * elementData(int index) * ensureCapacity(int minCapacity) * iterator() * listIterator(int index) * 总结 # ArrayList的特点 # 1、继承了AbstractList类,实现了RandomAccess、Cloneable、Serializable接口 2、底层是一个Object数组,数组是在内存中一块连续的内存, 3、默认长度是10 4、扩容每次扩充为原来的1.5倍(向下取整) 5、有序,不唯一 6、提供给了内部类Itr,实现了Iterator接口,使用iterator方法实际上使用内部类中的实现 ## 成员变量 ## private static final long serialVersionUID = 8683452581122892189L; // 用于序列化与反序列化时验证版本是否一致 private static final int DEFAULT_CAPACITY = 10; // 默认初始化容量 private static final Object[] EMPTY_ELEMENTDATA = { }; // 空数组用来给空的实例来使用的 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = { }; // 默认容量的数组 transient Object[] elementData; // 一个空数组,真正用来储存数据的数组 private int size; // 集合实际存储元素的长度 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 最大数组容量 ## 构造方法 ## * **无参构造方法** 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); } } * **有参构造方法(参数为实现了Connection接口的集合类)** public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // 当数组中存有元素 if (elementData.getClass() != Object[].class) // 判断数组是不是Object类型的 elementData = Arrays.copyOf(elementData, size, Object[].class); // 生成一个Object类型的数组 } else { // 数组中不存在元素 this.elementData = EMPTY_ELEMENTDATA; // 赋值一个空数组 } } ## add(E e) ## /** * 添加元素 */ public boolean add(E e) { ensureCapacityInternal(size + 1); // 用来检测是否需要扩容,来确保ArrayList的内部容量足够 elementData[size++] = e; // 对数组下标为size的位置赋值为e,然后size++ return true; } /** * 计算最小容量 */ private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 如果elementData为空数组 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // 获取默认容量10和所需最小容量中的最大值,如果为ArrayList第一次add,则ArrayList的容量为DEFAULT_CAPACITY=10,如果ArrayList不为第一次add,则此if条件为false,根本不走这步 } ensureExplicitCapacity(minCapacity); // 判断是否需要扩容 } /** * 判断是否需要扩容 */ private void ensureExplicitCapacity(int minCapacity) { modCount++; // 修改次数加1 if (minCapacity - elementData.length > 0) // 所需要的最小容量比当前集合的容量还大,如果为第一次add,即minCapacity=10,elementData.length=0,需要扩容,最后扩容为10,如果不是第一次add,则需判断集合的size(实际储存元素的个数)+1是否大于集合的length(容量或者长度) grow(minCapacity); // 数组扩容 } /** * 数组扩容 */ private void grow(int minCapacity) { int oldCapacity = elementData.length; // 老的(扩容之前的)ArrayList集合的长度 int newCapacity = oldCapacity + (oldCapacity >> 1); // 新的(准备扩容的大小,还不是最终要扩容的大小)容量=旧的容量+旧的容量/2(相当于原来的1.5倍) if (newCapacity - minCapacity < 0) // 如果扩容完还不够 newCapacity = minCapacity; // 将所需的容量赋值给新的容量 if (newCapacity - MAX_ARRAY_SIZE > 0) // 如果扩容后的大小比最大数组容量大小还大,数组的容量是有限的,最大允许MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8,如果还需要的话只能到,最后只能到Integer.MAX_VALUE newCapacity = hugeCapacity(minCapacity); // 获取最大容量 elementData = Arrays.copyOf(elementData, newCapacity); // 将老的数据拷贝一份,再将新的容量赋值给新的数组,再将新的数组赋值给新的数组的引用 } /** * 获取最大容量 */ private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } ## add(int index, E element) ## /** * 在指定下标index的位置上添加元素 */ public void add(int index, E element) { rangeCheckForAdd(index); // 判断下标index是否越界 ensureCapacityInternal(size + 1); // 和上面的add(E e)方法一样,检测是否需要扩容 System.arraycopy(elementData, index, elementData, index + 1, size - index); // 将index起及其之后的所有元素向后移动一位 elementData[index] = element; // 为下标为index上赋新值 size++; } /** * 判断下标index是否越界 */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 计算最小容量 */ private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 如果elementData为空数组 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // 获取默认容量10和所需最小容量中的最大值,如果为ArrayList第一次add,则ArrayList的容量为DEFAULT_CAPACITY=10,如果ArrayList不为第一次add,则此if条件为false,根本不走这步 } ensureExplicitCapacity(minCapacity); // 判断是否需要扩容 } /** * 判断是否需要扩容 */ private void ensureExplicitCapacity(int minCapacity) { modCount++; // 修改次数加1 if (minCapacity - elementData.length > 0) // 所需要的最小容量比当前集合的容量还大,如果为第一次add,即minCapacity=10,elementData.length=0,需要扩容,最后扩容为10,如果不是第一次add,则需判断集合的size(实际储存元素的个数)+1是否大于集合的length(容量或者长度) grow(minCapacity); // 数组扩容 } /** * 数组扩容 */ private void grow(int minCapacity) { int oldCapacity = elementData.length; // 老的(扩容之前的)ArrayList集合的长度 int newCapacity = oldCapacity + (oldCapacity >> 1); // 新的(准备扩容的大小,还不是最终要扩容的大小)容量=旧的容量+旧的容量/2(相当于原来的1.5倍) if (newCapacity - minCapacity < 0) // 如果扩容完还不够 newCapacity = minCapacity; // 将所需的容量赋值给新的容量 if (newCapacity - MAX_ARRAY_SIZE > 0) // 如果扩容后的大小比最大数组容量大小还大,数组的容量是有限的,最大允许MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8,如果还需要的话只能到,最后只能到Integer.MAX_VALUE newCapacity = hugeCapacity(minCapacity); // 获取最大容量 elementData = Arrays.copyOf(elementData, newCapacity); // 将老的数据拷贝一份,再将新的容量赋值给新的数组,再将新的数组赋值给新的数组的引用 } /** * 获取最大容量 */ private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } ## addAll(Collection<? extends E> c) ## /** * 添加一个集合,然后返回一个新的ArrayList */ public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // 用来检测是否需要扩容,来确保ArrayList的内部容量足够 System.arraycopy(a, 0, elementData, size, numNew); // 将elementData和a数组合并和返回一个新的数组 size += numNew; return numNew != 0; } ## addAll(int index, Collection<? extends E> c) ## /** * 在指定下标index出添加一个集合,index+1及其之后的往后移,然后返回一个新的ArrayList */ public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); // 检测下标index是否数组越界 Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // 用来检测是否需要扩容,来确保ArrayList的内部容量足够 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; } ## remove(int index) ## /** * 删除指定下标index位置的元素 */ public E remove(int index) { rangeCheck(index); // 检测index是否越界 modCount++; // 修改次数加1 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; // 清除原本最后一位的元素设置为null,因为在下标为index的位置上删除了一个元素,index+1及其之后的元素往移动后,原本elementData[size]的位置还是之前elementData[size],需要将其设置为null return oldValue; // 返回要删除的元素 } /** * 检测index是否越界 */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 获取elementData数组指定下标index的元素 */ E elementData(int index) { return (E) elementData[index]; } ## 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; } /** * 快速删除,和remove方法相比,少了一步rangeCheck(index);来检测index是否越界,但是该方法是根据元素来删除的就不需要检测了 */ 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; } ## removeAll(Collection<?> c) ## /** * 从此列表中删除指定集合中包含的所有元素 */ public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); // 检测元素是否为null return batchRemove(c, false); // 从此列表中删除指定集合中包含的所有元素 } /** * 检测元素是否为null */ public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; } /** * 从此列表中删除指定集合中包含的所有元素 */ 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 { 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; } ## retainAll(Collection<?> c) ## /** * 仅保留此列表中包含在指定集合中的元素 */ public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); } /** * 检测元素是否为null */ public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; } /** * 从此列表中删除指定集合中包含的所有元素 */ 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; } ## get(int index) ## /** * 底层使用Arrays.copyOf()方法将elementData转换成一个size(ArrayList实际的大小)大小的指定类型的数组 */ public E get(int index) { rangeCheck(index); // 检测下标index是否数组越界 return elementData(index); } /** * 判断下标index是否越界 */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 获取指定下标处的元素(由于没有对下标index判断是否越界) */ E elementData(int index) { return (E) elementData[index]; } ## set(int index, E element) ## /** * 在指定下标index处用指定元素替代,同时将被替代的元素返回 */ public E set(int index, E element) { rangeCheck(index); // 检测下标index是否数组越界 E oldValue = elementData(index); // 获取要被替代的元素 elementData[index] = element; return oldValue; } /** * 判断下标index是否越界 */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 获取指定下标处的元素(由于没有对下标index判断是否越界) */ E elementData(int index) { return (E) elementData[index]; } ## clear() ## /** * 清空ArrayList中的元素 * 根据源码可以发现,执行了clear()方法,ArrayList的元素全部置为null,但是ArrayList的length(容量)还是为之前的容量 */ public void clear() { modCount++; // 修改次数加1 for (int i = 0; i < size; i++) // 循环遍历实际元素的大小,将其设置为null elementData[i] = null; size = 0; // 最后size(ArrayList实际大小)设置为0 } ## contains(Object o) ## /** * 判断ArrayList中是否包含该元素 */ public boolean contains(Object o) { return indexOf(o) >= 0; } /** * 循环遍历elementData数组来并返回该元素下标index */ public int indexOf(Object o) { if (o == null) { // 判断该元素是否为null,避免发生NullPointerException(空指针异常) 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; } ## isEmpty() ## /** * 判断该ArrayList的实际容量是否为空 */ public boolean isEmpty() { return size == 0; } ## trimToSize() ## /** * 将elementData的数组设置为ArrayList实际的容量,删除动态增长中多余的容量 */ public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } } ## size() ## /** * 返回该ArrayList实际的容量 */ public int size() { return size; } ## indexOf(Object o) ## /** * 循环遍历elementData数组来并返回该元素下标index */ public int indexOf(Object o) { if (o == null) { // 判断该元素是否为null,避免发生NullPointerException(空指针异常) 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; } ## lastIndexOf(Object o) ## /** * 从最后一个实际容量开始遍历到下标为0,找到最后一个出现该元素的下标index */ public int lastIndexOf(Object o) { if (o == null) { // 判断该元素是否为null,避免发生NullPointerException(空指针异常) 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() ## /** * 克隆一个ArrayList,该克隆为浅克隆,即克隆之后两个ArrayList的地址不一样,但是ArrayList里面的元素实际上是指向同一个元素 */ public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { throw new InternalError(e); } } ## toArray() ## /** * 底层使用Arrays.copyOf()方法将elementData转换成一个size(ArrayList实际的大小)大小的Object数组 */ public Object[] toArray() { return Arrays.copyOf(elementData, size); } ## toArray(T\[\] a) ## /** * 底层使用Arrays.copyOf()方法将elementData转换成一个size(ArrayList实际的大小)大小的指定类型的数组 */ public <T> T[] toArray(T[] a) { if (a.length < size) return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } ## elementData(int index) ## /** * 获取指定下标处的元素(由于没有对下标index判断是否越界) */ E elementData(int index) { return (E) elementData[index]; } ## ensureCapacity(int minCapacity) ## /** * 确保ArrayList集合至少可以容纳指定最小容量参数指定的元素数。 */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0: DEFAULT_CAPACITY; // 如果该集合为空,minExpand为10,需要 if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } ## iterator() ## /** * ArrayList迭代器方法 */ public Iterator<E> iterator() { return new Itr(); // ArrayList中内部类Itr实现了迭代器接口Iterator,使用ArrayList中的迭代器方法其实是调用ArrayList内部类Itr中的实现 } * Itr /** * ArrayList内部类Itr实现了迭代器接口Iterator */ private class Itr implements Iterator<E> { // ArrayList的内部类Itr实现了Iterator接口 int cursor; // 要返回的下一个元素的索引 int lastRet = -1; // 返回最后一个元素的索引; 如果没有这样的话返回-1 int expectedModCount = modCount; // Ttr内部的预期的modCount public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } @Override @SuppressWarnings("unchecked") public void forEachRemaining(Consumer<? super E> consumer) { Objects.requireNonNull(consumer); final int size = ArrayList.this.size; int i = cursor; if (i >= size) { return; } final Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) { throw new ConcurrentModificationException(); } while (i != size && modCount == expectedModCount) { consumer.accept((E) elementData[i++]); } cursor = i; lastRet = i - 1; checkForComodification(); } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } ## listIterator(int index) ## public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } * ListItr private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) { super(); cursor = index; } public boolean hasPrevious() { return cursor != 0; } public int nextIndex() { return cursor; } public int previousIndex() { return cursor - 1; } @SuppressWarnings("unchecked") public E previous() { checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[lastRet = i]; } public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { int i = cursor; ArrayList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } } # 总结 # * ArrayList在new出来的时候容量为0,在第一次add的时候会进行初始化,默初始化容量为10,并且递增因子为1.5(向下取整) * ArrayList底层是一个Object数组,能够动态扩容 * 因为ArrayList底层是一个数组,所以它查询快,能够快速定位元素,时间复杂度为O(1),但是增删慢。因为增加元素可能存在扩容,需要创建新数组,然后拷贝到新数组中;删除元素可能存在删除一个元素,然后后面的元素往前移动 * ArrayList中的iterator()和listIterator()方法ArrayList是在内部通过内部类实现了Iterator迭代器接口,实际是通过调用内部类进行操作的 * ArrayList是一个线程不安全的集合,但是ArrayList内部是通过fast-fail机制来提醒你出现了线程安全问题,避免你继续错下去,比如在使用迭代器遍历集合时: public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(1);list.add(2);list.add(3);list.add(4);list.add(5); Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { Integer integer = iterator.next(); if (integer == 3) { list.remove(1); } } } * 运行报错:`java.util.ConcurrentModificationException` Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851) at com.wyj.arraylist.ArrayListTests.main(ArrayListTests.java:23) * 查看源码: 在执行`Iterator<Integer> iterator = list.iterator();`的时候通过`int expectedModCount = modCount;`给expectedModCount赋值了,在执行`remove`方法时执行了`modCount++;`,但是在执行了下一次`next`方法时,执行了`checkForComodification()`方法来检测modCount是否发生变化,但是此时由于执行了`remove`方法`modCount++`了,所以`modCount != expectedModCount` final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } * 那如何正确在迭代器中移除元素呢 **使用Iterator中的remove方法即可**
还没有评论,来说两句吧...