当前位置: 首页 > news >正文

java ArrayList源码分析

ArrayList 是 Java 标准库中的一个非常常用的类,它实现了 List 接口,提供了一个动态数组的实现,可以用来存储一系列的元素。

以下是一些关键点的解释:

  1. serialVersionUID:用于序列化时保持类的版本一致性。
  2. DEFAULT_CAPACITY:默认的初始容量。
  3. elementData:用于存储列表元素的数组。
  4. size:列表中当前元素的数量。
  5. MAX_ARRAY_SIZE:可以分配给数组的最大大小。

构造函数:

  • ArrayList():创建一个空的 ArrayList
  • ArrayList(int initialCapacity):创建一个具有指定初始容量的 ArrayList
  • ArrayList(Collection<? extends E> c):创建一个包含指定集合中所有元素的 ArrayList

方法:

  • trimToSize():将 elementData 数组的大小调整为 size
  • ensureCapacity(int minCapacity):确保 elementData 数组至少有足够的最小容量。
  • add(E e):在列表末尾添加一个元素。
  • add(int index, E element):在指定位置插入一个元素。
  • remove(Object o):移除列表中第一次出现的指定元素。
  • remove(int index):移除指定位置的元素。
  • clear():移除列表中的所有元素。
  • addAll(Collection<? extends E> c):将指定集合中的所有元素添加到此列表的末尾。
  • addAll(int index, Collection<? extends E> c):将指定集合中的所有元素插入到此列表中的指定位置。
  • get(int index):返回指定位置的元素。
  • set(int index, E element):用指定元素替换指定位置的元素。
  • size():返回列表中的元素数量。

ArrayList 还实现了一些其他的内部方法和嵌套类,比如 Itr(迭代器)、ListItr(列表迭代器)、SubList(子列表)等,这些类和方法支持 ArrayList 的高级操作,如迭代、元素搜索、子列表操作等。

此外,ArrayList 还重写了 clone() 方法来实现浅拷贝,以及 toArray()toArray(T[] a) 方法来将列表转换为数组。

 ArrayList源代码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package java.util;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {private static final long serialVersionUID = 8683452581122892189L;private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA = new Object[0];private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];transient Object[] elementData;private int size;private static final int MAX_ARRAY_SIZE = 2147483639;public ArrayList(int var1) {if (var1 > 0) {this.elementData = new Object[var1];} else {if (var1 != 0) {throw new IllegalArgumentException("Illegal Capacity: " + var1);}this.elementData = EMPTY_ELEMENTDATA;}}public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}public ArrayList(Collection<? extends E> var1) {this.elementData = var1.toArray();if ((this.size = this.elementData.length) != 0) {if (this.elementData.getClass() != Object[].class) {this.elementData = Arrays.copyOf(this.elementData, this.size, Object[].class);}} else {this.elementData = EMPTY_ELEMENTDATA;}}public void trimToSize() {++this.modCount;if (this.size < this.elementData.length) {this.elementData = this.size == 0 ? EMPTY_ELEMENTDATA : Arrays.copyOf(this.elementData, this.size);}}public void ensureCapacity(int var1) {int var2 = this.elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA ? 0 : 10;if (var1 > var2) {this.ensureExplicitCapacity(var1);}}private void ensureCapacityInternal(int var1) {if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {var1 = Math.max(10, var1);}this.ensureExplicitCapacity(var1);}private void ensureExplicitCapacity(int var1) {++this.modCount;if (var1 - this.elementData.length > 0) {this.grow(var1);}}private void grow(int var1) {int var2 = this.elementData.length;int var3 = var2 + (var2 >> 1);if (var3 - var1 < 0) {var3 = var1;}if (var3 - 2147483639 > 0) {var3 = hugeCapacity(var1);}this.elementData = Arrays.copyOf(this.elementData, var3);}private static int hugeCapacity(int var0) {if (var0 < 0) {throw new OutOfMemoryError();} else {return var0 > 2147483639 ? 2147483647 : 2147483639;}}public int size() {return this.size;}public boolean isEmpty() {return this.size == 0;}public boolean contains(Object var1) {return this.indexOf(var1) >= 0;}public int indexOf(Object var1) {int var2;if (var1 == null) {for(var2 = 0; var2 < this.size; ++var2) {if (this.elementData[var2] == null) {return var2;}}} else {for(var2 = 0; var2 < this.size; ++var2) {if (var1.equals(this.elementData[var2])) {return var2;}}}return -1;}public int lastIndexOf(Object var1) {int var2;if (var1 == null) {for(var2 = this.size - 1; var2 >= 0; --var2) {if (this.elementData[var2] == null) {return var2;}}} else {for(var2 = this.size - 1; var2 >= 0; --var2) {if (var1.equals(this.elementData[var2])) {return var2;}}}return -1;}public Object clone() {try {ArrayList var1 = (ArrayList)super.clone();var1.elementData = Arrays.copyOf(this.elementData, this.size);var1.modCount = 0;return var1;} catch (CloneNotSupportedException var2) {throw new InternalError(var2);}}public Object[] toArray() {return Arrays.copyOf(this.elementData, this.size);}public <T> T[] toArray(T[] var1) {if (var1.length < this.size) {return (Object[])Arrays.copyOf(this.elementData, this.size, var1.getClass());} else {System.arraycopy(this.elementData, 0, var1, 0, this.size);if (var1.length > this.size) {var1[this.size] = null;}return var1;}}E elementData(int var1) {return this.elementData[var1];}public E get(int var1) {this.rangeCheck(var1);return this.elementData(var1);}public E set(int var1, E var2) {this.rangeCheck(var1);Object var3 = this.elementData(var1);this.elementData[var1] = var2;return var3;}public boolean add(E var1) {this.ensureCapacityInternal(this.size + 1);this.elementData[this.size++] = var1;return true;}public void add(int var1, E var2) {this.rangeCheckForAdd(var1);this.ensureCapacityInternal(this.size + 1);System.arraycopy(this.elementData, var1, this.elementData, var1 + 1, this.size - var1);this.elementData[var1] = var2;++this.size;}public E remove(int var1) {this.rangeCheck(var1);++this.modCount;Object var2 = this.elementData(var1);int var3 = this.size - var1 - 1;if (var3 > 0) {System.arraycopy(this.elementData, var1 + 1, this.elementData, var1, var3);}this.elementData[--this.size] = null;return var2;}public boolean remove(Object var1) {int var2;if (var1 == null) {for(var2 = 0; var2 < this.size; ++var2) {if (this.elementData[var2] == null) {this.fastRemove(var2);return true;}}} else {for(var2 = 0; var2 < this.size; ++var2) {if (var1.equals(this.elementData[var2])) {this.fastRemove(var2);return true;}}}return false;}private void fastRemove(int var1) {++this.modCount;int var2 = this.size - var1 - 1;if (var2 > 0) {System.arraycopy(this.elementData, var1 + 1, this.elementData, var1, var2);}this.elementData[--this.size] = null;}public void clear() {++this.modCount;for(int var1 = 0; var1 < this.size; ++var1) {this.elementData[var1] = null;}this.size = 0;}public boolean addAll(Collection<? extends E> var1) {Object[] var2 = var1.toArray();int var3 = var2.length;this.ensureCapacityInternal(this.size + var3);System.arraycopy(var2, 0, this.elementData, this.size, var3);this.size += var3;return var3 != 0;}public boolean addAll(int var1, Collection<? extends E> var2) {this.rangeCheckForAdd(var1);Object[] var3 = var2.toArray();int var4 = var3.length;this.ensureCapacityInternal(this.size + var4);int var5 = this.size - var1;if (var5 > 0) {System.arraycopy(this.elementData, var1, this.elementData, var1 + var4, var5);}System.arraycopy(var3, 0, this.elementData, var1, var4);this.size += var4;return var4 != 0;}protected void removeRange(int var1, int var2) {++this.modCount;int var3 = this.size - var2;System.arraycopy(this.elementData, var2, this.elementData, var1, var3);int var4 = this.size - (var2 - var1);for(int var5 = var4; var5 < this.size; ++var5) {this.elementData[var5] = null;}this.size = var4;}private void rangeCheck(int var1) {if (var1 >= this.size) {throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1));}}private void rangeCheckForAdd(int var1) {if (var1 > this.size || var1 < 0) {throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1));}}private String outOfBoundsMsg(int var1) {return "Index: " + var1 + ", Size: " + this.size;}public boolean removeAll(Collection<?> var1) {Objects.requireNonNull(var1);return this.batchRemove(var1, false);}public boolean retainAll(Collection<?> var1) {Objects.requireNonNull(var1);return this.batchRemove(var1, true);}private boolean batchRemove(Collection<?> var1, boolean var2) {Object[] var3 = this.elementData;int var4 = 0;int var5 = 0;boolean var6 = false;while(true) {boolean var11 = false;try {var11 = true;if (var4 >= this.size) {var11 = false;break;}if (var1.contains(var3[var4]) == var2) {var3[var5++] = var3[var4];}++var4;} finally {if (var11) {if (var4 != this.size) {System.arraycopy(var3, var4, var3, var5, this.size - var4);var5 += this.size - var4;}if (var5 != this.size) {for(int var9 = var5; var9 < this.size; ++var9) {var3[var9] = null;}this.modCount += this.size - var5;this.size = var5;var6 = true;}}}}if (var4 != this.size) {System.arraycopy(var3, var4, var3, var5, this.size - var4);var5 += this.size - var4;}if (var5 != this.size) {for(int var7 = var5; var7 < this.size; ++var7) {var3[var7] = null;}this.modCount += this.size - var5;this.size = var5;var6 = true;}return var6;}private void writeObject(ObjectOutputStream var1) throws IOException {int var2 = this.modCount;var1.defaultWriteObject();var1.writeInt(this.size);for(int var3 = 0; var3 < this.size; ++var3) {var1.writeObject(this.elementData[var3]);}if (this.modCount != var2) {throw new ConcurrentModificationException();}}private void readObject(ObjectInputStream var1) throws IOException, ClassNotFoundException {this.elementData = EMPTY_ELEMENTDATA;var1.defaultReadObject();var1.readInt();if (this.size > 0) {this.ensureCapacityInternal(this.size);Object[] var2 = this.elementData;for(int var3 = 0; var3 < this.size; ++var3) {var2[var3] = var1.readObject();}}}public ListIterator<E> listIterator(int var1) {if (var1 >= 0 && var1 <= this.size) {return new ArrayList.ListItr(var1);} else {throw new IndexOutOfBoundsException("Index: " + var1);}}public ListIterator<E> listIterator() {return new ArrayList.ListItr(0);}public Iterator<E> iterator() {return new ArrayList.Itr();}public List<E> subList(int var1, int var2) {subListRangeCheck(var1, var2, this.size);return new ArrayList.SubList(this, 0, var1, var2);}static void subListRangeCheck(int var0, int var1, int var2) {if (var0 < 0) {throw new IndexOutOfBoundsException("fromIndex = " + var0);} else if (var1 > var2) {throw new IndexOutOfBoundsException("toIndex = " + var1);} else if (var0 > var1) {throw new IllegalArgumentException("fromIndex(" + var0 + ") > toIndex(" + var1 + ")");}}public void forEach(Consumer<? super E> var1) {Objects.requireNonNull(var1);int var2 = this.modCount;Object[] var3 = (Object[])this.elementData;int var4 = this.size;for(int var5 = 0; this.modCount == var2 && var5 < var4; ++var5) {var1.accept(var3[var5]);}if (this.modCount != var2) {throw new ConcurrentModificationException();}}public Spliterator<E> spliterator() {return new ArrayList.ArrayListSpliterator(this, 0, -1, 0);}public boolean removeIf(Predicate<? super E> var1) {Objects.requireNonNull(var1);int var2 = 0;BitSet var3 = new BitSet(this.size);int var4 = this.modCount;int var5 = this.size;for(int var6 = 0; this.modCount == var4 && var6 < var5; ++var6) {Object var7 = this.elementData[var6];if (var1.test(var7)) {var3.set(var6);++var2;}}if (this.modCount != var4) {throw new ConcurrentModificationException();} else {boolean var10 = var2 > 0;if (var10) {int var11 = var5 - var2;int var8 = 0;for(int var9 = 0; var8 < var5 && var9 < var11; ++var9) {var8 = var3.nextClearBit(var8);this.elementData[var9] = this.elementData[var8];++var8;}for(var8 = var11; var8 < var5; ++var8) {this.elementData[var8] = null;}this.size = var11;if (this.modCount != var4) {throw new ConcurrentModificationException();}++this.modCount;}return var10;}}public void replaceAll(UnaryOperator<E> var1) {Objects.requireNonNull(var1);int var2 = this.modCount;int var3 = this.size;for(int var4 = 0; this.modCount == var2 && var4 < var3; ++var4) {this.elementData[var4] = var1.apply(this.elementData[var4]);}if (this.modCount != var2) {throw new ConcurrentModificationException();} else {++this.modCount;}}public void sort(Comparator<? super E> var1) {int var2 = this.modCount;Arrays.sort((Object[])this.elementData, 0, this.size, var1);if (this.modCount != var2) {throw new ConcurrentModificationException();} else {++this.modCount;}}static final class ArrayListSpliterator<E> implements Spliterator<E> {private final ArrayList<E> list;private int index;private int fence;private int expectedModCount;ArrayListSpliterator(ArrayList<E> var1, int var2, int var3, int var4) {this.list = var1;this.index = var2;this.fence = var3;this.expectedModCount = var4;}private int getFence() {int var1;if ((var1 = this.fence) < 0) {ArrayList var2;if ((var2 = this.list) == null) {var1 = this.fence = 0;} else {this.expectedModCount = var2.modCount;var1 = this.fence = var2.size;}}return var1;}public ArrayList.ArrayListSpliterator<E> trySplit() {int var1 = this.getFence();int var2 = this.index;int var3 = var2 + var1 >>> 1;return var2 >= var3 ? null : new ArrayList.ArrayListSpliterator(this.list, var2, this.index = var3, this.expectedModCount);}public boolean tryAdvance(Consumer<? super E> var1) {if (var1 == null) {throw new NullPointerException();} else {int var2 = this.getFence();int var3 = this.index;if (var3 < var2) {this.index = var3 + 1;Object var4 = this.list.elementData[var3];var1.accept(var4);if (this.list.modCount != this.expectedModCount) {throw new ConcurrentModificationException();} else {return true;}} else {return false;}}}public void forEachRemaining(Consumer<? super E> var1) {if (var1 == null) {throw new NullPointerException();} else {ArrayList var5;Object[] var6;if ((var5 = this.list) != null && (var6 = var5.elementData) != null) {int var3;int var4;if ((var3 = this.fence) < 0) {var4 = var5.modCount;var3 = var5.size;} else {var4 = this.expectedModCount;}int var2;if ((var2 = this.index) >= 0 && (this.index = var3) <= var6.length) {while(var2 < var3) {Object var7 = var6[var2];var1.accept(var7);++var2;}if (var5.modCount == var4) {return;}}}throw new ConcurrentModificationException();}}public long estimateSize() {return (long)(this.getFence() - this.index);}public int characteristics() {return 16464;}}private class Itr implements Iterator<E> {int cursor;int lastRet;int expectedModCount;private Itr() {this.lastRet = -1;this.expectedModCount = ArrayList.this.modCount;}public boolean hasNext() {return this.cursor != ArrayList.this.size;}public E next() {this.checkForComodification();int var1 = this.cursor;if (var1 >= ArrayList.this.size) {throw new NoSuchElementException();} else {Object[] var2 = ArrayList.this.elementData;if (var1 >= var2.length) {throw new ConcurrentModificationException();} else {this.cursor = var1 + 1;return var2[this.lastRet = var1];}}}public void remove() {if (this.lastRet < 0) {throw new IllegalStateException();} else {this.checkForComodification();try {ArrayList.this.remove(this.lastRet);this.cursor = this.lastRet;this.lastRet = -1;this.expectedModCount = ArrayList.this.modCount;} catch (IndexOutOfBoundsException var2) {throw new ConcurrentModificationException();}}}public void forEachRemaining(Consumer<? super E> var1) {Objects.requireNonNull(var1);int var2 = ArrayList.this.size;int var3 = this.cursor;if (var3 < var2) {Object[] var4 = ArrayList.this.elementData;if (var3 >= var4.length) {throw new ConcurrentModificationException();} else {while(var3 != var2 && ArrayList.this.modCount == this.expectedModCount) {var1.accept(var4[var3++]);}this.cursor = var3;this.lastRet = var3 - 1;this.checkForComodification();}}}final void checkForComodification() {if (ArrayList.this.modCount != this.expectedModCount) {throw new ConcurrentModificationException();}}}private class ListItr extends ArrayList<E>.Itr implements ListIterator<E> {ListItr(int var2) {super(null);this.cursor = var2;}public boolean hasPrevious() {return this.cursor != 0;}public int nextIndex() {return this.cursor;}public int previousIndex() {return this.cursor - 1;}public E previous() {this.checkForComodification();int var1 = this.cursor - 1;if (var1 < 0) {throw new NoSuchElementException();} else {Object[] var2 = ArrayList.this.elementData;if (var1 >= var2.length) {throw new ConcurrentModificationException();} else {this.cursor = var1;return var2[this.lastRet = var1];}}}public void set(E var1) {if (this.lastRet < 0) {throw new IllegalStateException();} else {this.checkForComodification();try {ArrayList.this.set(this.lastRet, var1);} catch (IndexOutOfBoundsException var3) {throw new ConcurrentModificationException();}}}public void add(E var1) {this.checkForComodification();try {int var2 = this.cursor;ArrayList.this.add(var2, var1);this.cursor = var2 + 1;this.lastRet = -1;this.expectedModCount = ArrayList.this.modCount;} catch (IndexOutOfBoundsException var3) {throw new ConcurrentModificationException();}}}private class SubList extends AbstractList<E> implements RandomAccess {private final AbstractList<E> parent;private final int parentOffset;private final int offset;int size;SubList(AbstractList<E> var2, int var3, int var4, int var5) {this.parent = var2;this.parentOffset = var4;this.offset = var3 + var4;this.size = var5 - var4;this.modCount = ArrayList.this.modCount;}public E set(int var1, E var2) {this.rangeCheck(var1);this.checkForComodification();Object var3 = ArrayList.this.elementData(this.offset + var1);ArrayList.this.elementData[this.offset + var1] = var2;return var3;}public E get(int var1) {this.rangeCheck(var1);this.checkForComodification();return ArrayList.this.elementData(this.offset + var1);}public int size() {this.checkForComodification();return this.size;}public void add(int var1, E var2) {this.rangeCheckForAdd(var1);this.checkForComodification();this.parent.add(this.parentOffset + var1, var2);this.modCount = this.parent.modCount;++this.size;}public E remove(int var1) {this.rangeCheck(var1);this.checkForComodification();Object var2 = this.parent.remove(this.parentOffset + var1);this.modCount = this.parent.modCount;--this.size;return var2;}protected void removeRange(int var1, int var2) {this.checkForComodification();this.parent.removeRange(this.parentOffset + var1, this.parentOffset + var2);this.modCount = this.parent.modCount;this.size -= var2 - var1;}public boolean addAll(Collection<? extends E> var1) {return this.addAll(this.size, var1);}public boolean addAll(int var1, Collection<? extends E> var2) {this.rangeCheckForAdd(var1);int var3 = var2.size();if (var3 == 0) {return false;} else {this.checkForComodification();this.parent.addAll(this.parentOffset + var1, var2);this.modCount = this.parent.modCount;this.size += var3;return true;}}public Iterator<E> iterator() {return this.listIterator();}public ListIterator<E> listIterator(final int var1) {this.checkForComodification();this.rangeCheckForAdd(var1);final int var2 = this.offset;return new ListIterator<E>() {int cursor = var1;int lastRet = -1;int expectedModCount;{this.expectedModCount = ArrayList.this.modCount;}public boolean hasNext() {return this.cursor != SubList.this.size;}public E next() {this.checkForComodification();int var1x = this.cursor;if (var1x >= SubList.this.size) {throw new NoSuchElementException();} else {Object[] var2x = ArrayList.this.elementData;if (var2 + var1x >= var2x.length) {throw new ConcurrentModificationException();} else {this.cursor = var1x + 1;return var2x[var2 + (this.lastRet = var1x)];}}}public boolean hasPrevious() {return this.cursor != 0;}public E previous() {this.checkForComodification();int var1x = this.cursor - 1;if (var1x < 0) {throw new NoSuchElementException();} else {Object[] var2x = ArrayList.this.elementData;if (var2 + var1x >= var2x.length) {throw new ConcurrentModificationException();} else {this.cursor = var1x;return var2x[var2 + (this.lastRet = var1x)];}}}public void forEachRemaining(Consumer<? super E> var1x) {Objects.requireNonNull(var1x);int var2x = SubList.this.size;int var3 = this.cursor;if (var3 < var2x) {Object[] var4 = ArrayList.this.elementData;if (var2 + var3 >= var4.length) {throw new ConcurrentModificationException();} else {while(var3 != var2x && SubList.this.modCount == this.expectedModCount) {var1x.accept(var4[var2 + var3++]);}this.lastRet = this.cursor = var3;this.checkForComodification();}}}public int nextIndex() {return this.cursor;}public int previousIndex() {return this.cursor - 1;}public void remove() {if (this.lastRet < 0) {throw new IllegalStateException();} else {this.checkForComodification();try {SubList.this.remove(this.lastRet);this.cursor = this.lastRet;this.lastRet = -1;this.expectedModCount = ArrayList.this.modCount;} catch (IndexOutOfBoundsException var2x) {throw new ConcurrentModificationException();}}}public void set(E var1x) {if (this.lastRet < 0) {throw new IllegalStateException();} else {this.checkForComodification();try {ArrayList.this.set(var2 + this.lastRet, var1x);} catch (IndexOutOfBoundsException var3) {throw new ConcurrentModificationException();}}}public void add(E var1x) {this.checkForComodification();try {int var2x = this.cursor;SubList.this.add(var2x, var1x);this.cursor = var2x + 1;this.lastRet = -1;this.expectedModCount = ArrayList.this.modCount;} catch (IndexOutOfBoundsException var3) {throw new ConcurrentModificationException();}}final void checkForComodification() {if (this.expectedModCount != ArrayList.this.modCount) {throw new ConcurrentModificationException();}}};}public List<E> subList(int var1, int var2) {ArrayList.subListRangeCheck(var1, var2, this.size);return ArrayList.this.new SubList(this, this.offset, var1, var2);}private void rangeCheck(int var1) {if (var1 < 0 || var1 >= this.size) {throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1));}}private void rangeCheckForAdd(int var1) {if (var1 < 0 || var1 > this.size) {throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1));}}private String outOfBoundsMsg(int var1) {return "Index: " + var1 + ", Size: " + this.size;}private void checkForComodification() {if (ArrayList.this.modCount != this.modCount) {throw new ConcurrentModificationException();}}public Spliterator<E> spliterator() {this.checkForComodification();return new ArrayList.ArrayListSpliterator(ArrayList.this, this.offset, this.offset + this.size, this.modCount);}}
}

接下来重点分析下 ArrayList 中的 addremoveensureCapacityInternal 方法。

1. add(E e) 方法

add(E e) 方法用于在 ArrayList 的末尾添加一个元素。以下是该方法的详细步骤:

  • 检查容量:首先,调用 ensureCapacityInternal 方法确保 elementData 数组有足够的空间来存储新的元素。如果数组容量不足以容纳更多的元素,它将被扩展。
  • 添加元素:在 elementData 数组的末尾(即 size 索引处)添加元素 e
  • 更新大小:将 size 增加 1,以反映列表中新增的元素。
  • 返回值:返回 true,表示元素成功添加。
public boolean add(E e) {ensureCapacityInternal(size + 1);  // 确保数组容量足够elementData[size++] = e;           // 在末尾添加元素return true;
}

2. remove(Object o) 方法

remove(Object o) 方法用于从 ArrayList 中移除第一个匹配的元素。以下是该方法的详细步骤:

  • 检查元素是否存在:遍历 elementData 数组,查找第一次出现的元素 o
  • 移除元素:如果找到元素,调用 fastRemove 方法来实际移除该元素。
    • 数组复制:将移除元素之后的所有元素向前移动一个位置,以填补空出来的位置。
    • 更新大小:将 size 减少 1。
    • 返回值:返回被移除的元素。
  • 未找到元素:如果遍历完整个数组都没有找到元素 o,则返回 false
public boolean remove(Object o) {int index;if (o == null) {for (index = 0; index < size; index++) {if (elementData[index] == null) {fastRemove(index);return true;}}} else {for (index = 0; index < size; index++) {if (o.equals(elementData[index])) {fastRemove(index);return true;}}}return false;
}

3. ensureCapacityInternal(int minCapacity) 方法

ensureCapacityInternal(int minCapacity) 方法用于确保 elementData 数组有足够的容量来存储至少 minCapacity 个元素。以下是该方法的详细步骤:

  • 默认容量检查:如果 elementData 数组是默认容量的空数组(DEFAULTCAPACITY_EMPTY_ELEMENTDATA),则根据需要将 minCapacity 调整为至少 10。
  • 调用 ensureExplicitCapacity:调用 ensureExplicitCapacity 方法来确保数组的实际容量至少为 minCapacity
  • 扩展数组:如果当前数组容量小于 minCapacity,则调用 grow 方法来扩展数组。
    • 计算新容量:在 grow 方法中,计算新的目标容量,通常是当前容量的 1.5 倍,但不超过最大数组大小限制。
    • 复制数组:使用 Arrays.copyOf 方法复制数组,以新的容量创建新数组,并将旧数组的元素复制到新数组中。
private void ensureCapacityInternal(int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math.max(10, minCapacity);}ensureExplicitCapacity(minCapacity);
}private void ensureExplicitCapacity(int minCapacity) {modCount++;if (minCapacity - elementData.length > 0)grow(minCapacity);
}private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);
}

这些方法展示了 ArrayList 如何管理其内部数组的容量和元素,确保在添加和删除元素时能够高效地操作。

以下是关于ArrayList部分的总结:

  • 线程安全ArrayList 不是线程安全的。在多线程环境中,需要外部同步或者使用 Collections.synchronizedList 方法来包装 ArrayList,以确保线程安全。
  • 迭代器安全:在使用迭代器遍历 ArrayList 时,不能对列表进行结构性修改(如添加或删除元素),否则会抛出 ConcurrentModificationException。如果需要在遍历过程中修改列表,可以使用 Iterator 的 remove 方法或 ListIterator 的 add 和 set 方法。
  • 容量限制ArrayList 的最大容量约为2^31-4(MAX_ARRAY_SIZE),超过这个限制将无法分配内存。

性能

  • 随机访问ArrayList 支持 O(1) 时间复杂度的随机访问,适合频繁读取元素的场景。
  • 添加和删除
    • 在列表末尾添加或删除元素是高效的,时间复杂度为 O(1)。
    • 在列表开头或中间添加或删除元素可能较慢,因为涉及到数组元素的移动,平均时间复杂度为 O(n)。
  • 内存使用ArrayList 会根据需要自动调整容量,但这种动态扩容机制可能导致初始阶段内存使用不是最优的。如果已知列表的大致大小,可以在创建时指定初始容量,以减少扩容操作。
  • 性能陷阱:频繁进行小容量扩容可能导致性能问题,尤其是在大量元素添加的场景下。合理预估初始容量可以减少扩容次数,提高性能。

最佳实践

  • 预估大小:如果已知列表的大致大小,创建时指定初始容量可以提高性能,减少扩容操作。
  • 避免索引越界:在访问元素时,确保索引在有效范围内,避免 IndexOutOfBoundsException
  • 使用迭代器:在需要遍历列表时,使用迭代器而不是手动管理索引,可以更安全、方便地操作列表。
  • 考虑其他数据结构:如果需要频繁在列表开头或中间进行插入和删除操作,可以考虑使用 LinkedList,它在这些操作中表现更好。


http://www.mrgr.cn/news/52362.html

相关文章:

  • 编写Python 自动化安装openGauss 数据库方法和代码 (1)
  • C++类与对象-继承和多态(超全整理)
  • msvcp140.dll重新安装的解决方法,msvcp140.dll丢失快速修复教程
  • PDF 软件如何帮助您编辑、转换和保护文件
  • 谷歌seo如何找到和优化相关关键词?
  • c++入门 类和对象(下)
  • Centos6.4升级Python的曲曲折折
  • 上海数据集团到访蓝象智联 探讨数据基础设施建设
  • Python必知必会:15个Python字符串格式化技巧!
  • 前端工具函数库
  • <el-input-number> 回车自动失去焦点
  • 学习文档10/17
  • 2024年100道最新软件测试面试题,常见面试题及答案汇总
  • Python中cls是什么?
  • gsd ijhdsuif hdsuhf u
  • java算法OJ(4)树与二叉树
  • 读论文框架
  • 离线数仓(2)
  • 浅谈SpringBoot读取application配置文件流程
  • Whisper 音视频转写