/** * * 元素数组 * * 当添加新的元素时,如果该数组容量不足,会创建新数组,并将原数组的元素拷贝到新数组。 * 之后,将该变量的内存地址指向该新数组。 * * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData ``` DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access
/** * * 已使用的数组的大小 * * The size of the ArrayList (the number of elements it contains). * * @serial */ privateint size;
/** * 无参数构造 * * Constructs an empty list with an initial capacity of ten. */ publicArrayList(){ this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
#ArrayList(Collection<? extends E> c)
传入 c 集合,作为 ArrayList 的 elementData 进行初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
publicArrayList(Collection<? extends E> c){ // 将c转换为Object数组 elementData = c.toArray(); // 如果数组长度大于0 if ((size = elementData.length) != 0) { // defend against c.toArray (incorrectly) not returning Object[] // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652) // 如果集合元素不是Object[]类型, 则会创建新的Object[], 并将elementData赋值到其中, 最后赋值给elementData if (elementData.getClass() != Object[].class) elementData= Arrays.copyOf(elementData, size, Object[].class); // 如果数组长度等于0, 则使用EMPTY_ELEMENTDATA } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
intindexOfRange(Object o, int start, int end){ Object[] es = elementData; // o为null的情况 if (o ``` null) { for (int i = start; i < end; i++) { if (es[i] ``` null) { return i; } } // o非null的情况 } else { for (int i = start; i < end; i++) { if (o.equals(es[i])) { return i; } } } // 找不到返回-1 return -1; }
intlastIndexOfRange(Object o, int start, int end){ Object[] es = elementData; // o为null的情况 if (o ``` null) { for (int i = end - 1; i >= start; i--) { if (es[i] ``` null) { return i; } } // o非null的情况 } else { for (int i = end - 1; i >= start; i--) { if (o.equals(es[i])) { return i; } } } // 找不到返回-1 return -1; }
7.4.#get(int index)——获取指定位置元素
1 2 3 4 5 6
public E get(int index){ // 校验index不超过size Objects.checkIndex(index, size); // 获得index位置的元素--时间复杂度为O(1) return elementData(index); }
7.5. #set(int index, E element)——在指定位置设定元素
1 2 3 4 5 6 7 8 9 10
public E set(int index, E element){ // 校验index不超过size Objects.checkIndex(index, size); // 获得index位置原来的值 E oldValue = elementData(index); // 修改index位置为新值 elementData[index] = element; // 返回旧值 return oldValue; }
/** * * 实现ArrayList数组的序列化 * */ @java.io.Serial privatevoidwriteObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out element count, and any hidden stuff // 获得当前数组的修改次数 int expectedModCount = modCount; // 写入非静态属性, 非transient属性 s.defaultWriteObject();
// Write out size as capacity for behavioral compatibility with clone() // 写入size, 主要为了与clone方法兼容 s.writeInt(size);
// Write out all elements in the proper order. // 逐个写入elementData数组的元素 // elementData是transient定义的, 并不一定全满, 容量有一定的预留 // 直接序列化, 会造成空间的浪费, 所以只序列化[0, size)的元素 for (int i=0; i<size; i++) { s.writeObject(elementData[i]); }
// Read in size, and any hidden stuff // 读取非静态、非transient属性 s.defaultReadObject();
// Read in capacity // 读取size, 不过忽略不用 s.readInt(); // ignored
if (size > 0) { // like clone(), allocate array based upon size not capacity SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size); // 创建elements数组 Object[] elements = new Object[size];
// Read in all elements in the proper order. // 逐个读取 for (int i = 0; i < size; i++) { elements[i] = s.readObject(); }
public Object[] toArray() { return Arrays.copyOf(elementData, size); }
转换成指定类型数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14
@SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { // 如果传入的数组小于size大小, 则直接复制一个新数组返回 if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); // 将elementData复制到a中 System.arraycopy(elementData, 0, a, 0, size); // 如果传入的数组长度大于size, 则将a[size]赋值为null if (a.length > size) a[size] = null; // 返回a return a; }
publicbooleanequals(Object o){ // 如果是自己, 直接返回true if (o ``` this) { returntrue; }
// 如果不是List类型, 直接返回false if (!(o instanceof List)) { returnfalse; }
finalint expectedModCount = modCount; // ArrayList can be subclassed and given arbitrary behavior, but we can // still deal with the common case where o is ArrayList precisely // 根据不同类型, 调用不同比对的方法. // 主要考虑ArrayList可以直接使用其elementData属性, 性能更优 boolean equal = (o.getClass() ``` ArrayList.class) ? equalsArrayList((ArrayList<?>) o) : equalsRange((List<?>) o, 0, size);
booleanequalsRange(List<?> other, int from, int to){ // 如果to大于es的大小, 说明数组发生改变, 抛出异常 final Object[] es = elementData; if (to > es.length) { thrownew ConcurrentModificationException(); } // 通过迭代器遍历other, 然后逐个元素对比 var oit = other.iterator(); for (; from < to; from++) { // 如果oit没有下一个, 或者元素不相等, 返回false不匹配 if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) { returnfalse; } } // 通过oit是否遍历完, 实现大小是否相等效果 return !oit.hasNext(); }
privatebooleanequalsArrayList(ArrayList<?> other){ // 获得other数组的修改次数 finalint otherModCount = other.modCount; finalint s = size; boolean equal; // 判断数组大小是否相等 if (equal = (s ``` other.size)) { final Object[] otherEs = other.elementData; final Object[] es = elementData; // 如果s大于es或者otherEs的长度, 说明发生变化, 抛出异常 if (s > es.length || s > otherEs.length) { thrownew ConcurrentModificationException(); } // 遍历, 逐个比较每个元素是否相等 for (int i = 0; i < s; i++) { if (!Objects.equals(es[i], otherEs[i])) { equal = false; break; // 如果不相等, break } } } // 如果other修改次数发生变化, 则抛出ConcurrentModificationException异常 other.checkForComodification(otherModCount); return equal; }
99.4.#clear()——清空数组
1 2 3 4 5 6 7 8
publicvoidclear(){ // 增加数组修改次数 modCount++; // 遍历数组, 倒序设置为null final Object[] es = elementData; for (int to = size, i = size = 0; i < to; i++) es[i] = null; }
99.5.#clone()——克隆
1 2 3 4 5 6 7 8 9 10 11 12 13 14
public Object clone(){ try { // 调用父类, 进行克隆 ArrayList<?> v = (ArrayList<?>) super.clone(); // 拷贝一个新的数组 v.elementData = Arrays.copyOf(elementData, size); // 设置新数组修改次数为0 v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable thrownew InternalError(e); } }