ArrayList源码分析,你需要知道的所有知识点!("深入解析ArrayList源码:你需要掌握的核心知识点全览!")

原创
ithorizon 6个月前 (10-19) 阅读数 26 #后端开发

深入解析ArrayList源码:你需要掌握的核心知识点全览!

一、ArrayList简介

ArrayList是Java中常用的动态数组实现,它提供了类似于数组的随机访问能力,同时具有动态扩展数组长度的特性。下面我们将深入分析ArrayList的源码,以掌握其核心知识点。

二、ArrayList的核心属性

ArrayList的核心属性核心包括以下几个:

// 默认初始容量

private static final int DEFAULT_CAPACITY = 10;

// 空数组实例

private static final Object[] EMPTY_ELEMENTDATA = {};

// 存储元素的数组

transient Object[] elementData;

// 实际元素数量

private int size;

其中,elementData是存储元素的数组,是ArrayList的核心。

三、构造函数

ArrayList提供了多种构造函数,以下是几种常见的构造函数实现:

// 默认构造函数

public ArrayList() {

this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

// 指定初始容量的构造函数

public ArrayList(int initialCapacity) {

if (initialCapacity >= 0) {

this.elementData = new Object[initialCapacity];

} else {

throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);

}

}

// 从Collection集合中构造ArrayList

public ArrayList(Collection c) {

elementData = c.toArray();

if ((size = elementData.length) != 0) {

// c.toArray might (incorrectly) not return Object[]

// array with >= c.size().emptyCheck uses (size==0) trick to check this

if (elementData.getClass() != Object[].class)

elementData = Arrays.copyOf(elementData, size);

} else {

// replace with empty array.

this.elementData = EMPTY_ELEMENTDATA;

}

}

四、扩容机制

ArrayList的扩容机制是其核心特性之一。当数组容量不足以容纳更多元素时,ArrayList会自动扩容。以下是扩容方法的核心实现:

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);

}

private void grow(int minCapacity) {

// overflow-conscious code

int oldCapacity = elementData.length;

int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为原来的1.5倍

if (newCapacity - minCapacity < 0)

newCapacity = minCapacity;

if (newCapacity - MAX_ARRAY_SIZE > 0)

newCapacity = hugeCapacity(minCapacity);

elementData = Arrays.copyOf(elementData, newCapacity);

}

扩容过程核心包括检查当前数组是否需要扩容,如果需要,则将数组容量扩大为原来的1.5倍。

五、添加元素

ArrayList提供了多种添加元素的方法,以下是添加元素到数组末尾的方法实现:

public boolean add(E e) {

ensureCapacityInternal(size + 1); // 确保数组有足够空间

elementData[size++] = e; // 添加元素到数组末尾

return true;

}

在添加元素之前,会先调用ensureCapacityInternal方法确保数组有足够的空间。

六、随机访问元素

ArrayList赞成随机访问元素,以下是随机访问元素的方法实现:

public E get(int index) {

rangeCheck(index);

return elementData(index);

}

E elementData(int index) {

return (E) elementData[index];

}

private void rangeCheck(int index) {

if (index >= size)

throw new IndexOutOfBoundsException(outOfBoundsMessage(index));

}

随机访问元素的时间错综度为O(1),这是由于ArrayList底层是通过数组实现的。

七、删除元素

ArrayList提供了删除元素的方法,以下是删除指定索引元素的方法实现:

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;

}

删除元素后,需要将被删除元素之后的所有元素向前移动一位,以填补空缺。

八、遍历元素

ArrayList赞成多种遍历行为,以下是使用迭代器遍历元素的示例:

public Iterator iterator() {

return new Itr();

}

private class Itr implements Iterator {

int cursor; // index of next element to return

int lastRet = -1; // index of last element returned; -1 if no such

int expectedModCount = 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();

}

}

final void checkForComodification() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

}

}

迭代器在遍历过程中,会检查modCount值,以确保在遍历过程中ArrayList没有出现结构性修改。

九、序列化和反序列化

ArrayList实现了Serializable接口,于是赞成序列化和反序列化。以下是序列化方法的核心实现:

private void writeObject(java.io.ObjectOutputStream s)

throws java.io.IOException {

int expectedModCount = modCount;

s.defaultWriteObject();

s.writeInt(size); // 写入数组实际元素数量

for (int i=0; i

s.writeObject(elementData[i]); // 写入每个元素

}

if (modCount != expectedModCount) {

throw new ConcurrentModificationException();

}

}

反序列化过程则是将序列化的数据恢复为ArrayList实例。

十、总结

ArrayList是Java中常用的动态数组实现,其源码分析涉及构造函数、扩容机制、添加元素、随机访问元素、删除元素、遍历元素、序列化和反序列化等多个方面。掌握这些核心知识点,有助于我们更好地领会和运用ArrayList,尽或许降低损耗程序性能和稳定性。


本文由IT视界版权所有,禁止未经同意的情况下转发

文章标签: 后端开发


热门