構(gòu)造函數(shù)
ArrayList 有三個(gè)構(gòu)造函數(shù),默認(rèn)不帶參數(shù)的構(gòu)造函數(shù)就是初始化一個(gè)空數(shù)組。
//一個(gè)空數(shù)組
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//實(shí)際存儲(chǔ)元素的數(shù)組
transient Object[] elementData;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
帶一個(gè) int 類型的容量參數(shù)的構(gòu)造函數(shù),可以指定 ArrayList 的容量大小。
//空數(shù)組
private static final Object[] EMPTY_ELEMENTDATA = {};
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//容量大于 0 就構(gòu)建一個(gè) Object 的數(shù)組
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//容量等于 0 就是一個(gè)空數(shù)組
this.elementData = EMPTY_ELEMENTDATA;
} else {
//容量小于 0 拋出異常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
帶一個(gè)集合的構(gòu)造函數(shù), 將集合轉(zhuǎn)換成 Object[] 類型后拷貝到 elementData 中。
public ArrayList(Collection< ? extends E > c) {
//集合轉(zhuǎn)為數(shù)組
Object[] a = c.toArray();
if ((size = a.length) != 0) {
//集合是不是 ArrayList 類型
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
//將集合元素拷貝成 Object[] 到 elementData
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
//空元素
elementData = EMPTY_ELEMENTDATA;
}
}
常用函數(shù)
add()
先從 ArrayList 最常用的方法 add() 開始講起,add() 方法就是將元素添加到 elementData 的末尾。平均時(shí)間復(fù)雜度為 O(1)。
//ArrayList.add()
public boolean add(E e) {
//檢查數(shù)組是否存放的下
ensureCapacityInternal(size + 1);
//添加到末尾
elementData[size++] = e;
return true;
}
//ArrayList.ensureCapacityInternal()
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//ArrayList.calculateCapacity()
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//檢查時(shí)不是默認(rèn)時(shí)的空數(shù)組,是默認(rèn)時(shí)的空數(shù)組,初始化的容量就是 10
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//ArrayList.ensureExplicitCapacity()
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//ArrayList.grow()
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
//新長(zhǎng)度時(shí)原來長(zhǎng)度的 1.5 倍
int newCapacity = oldCapacity + (oldCapacity > > 1);
//新長(zhǎng)度小于實(shí)際容量,就用實(shí)際容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//新長(zhǎng)度太大了,就用最大的容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//copy 成一個(gè)新數(shù)組
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 擴(kuò)容的大小為原長(zhǎng)度+1/2的原長(zhǎng)度
- 如果擴(kuò)容長(zhǎng)度比傳入的最小容量小,則使用最小容量,如果擴(kuò)容長(zhǎng)度超過設(shè)定的最大容量,則實(shí)際用最大容量
- 初始化默認(rèn)長(zhǎng)度為10,當(dāng)添加到11個(gè)長(zhǎng)度時(shí),容量為15
add(int index, E element)
將元素插入到指定的位置,主要的操作是將指定位置之后的元素往后移動(dòng)一個(gè)位置,空出 index 位置。平均時(shí)間復(fù)雜度為 O(n)。
//ArrayList.add(int index, E element)
public void add(int index, E element) {
//index的越界檢查
rangeCheckForAdd(index);
//擴(kuò)容
ensureCapacityInternal(size + 1);
//將 index 之后的所有元素 copy 到往后挪動(dòng)一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//將 index 位置放入新元素
elementData[index] = element;
//數(shù)量 + 1
size++;
}
get()
get() 應(yīng)該是第二個(gè)常用的函數(shù),可以返回隨機(jī)位置的元素。需要注意的是越界時(shí),超過容量返回的是 IndexOutOfBoundsException 異常,index 太小返回的是 ArrayIndexOutOfBoundsException 異常。平均時(shí)間復(fù)雜度為 O(1)。
//ArrayList.get()
public E get(int index) {
//index 越界檢查
rangeCheck(index);
//返回指定位置的元素
return elementData(index);
}
//ArrayList.rangeCheck()
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//ArrayList.elementData()
E elementData(int index) {
return (E) elementData[index];
}
remove()
刪除指定位置的元素,并返回刪除的元素。平均時(shí)間復(fù)雜度為 O(n)。
//ArrayList.remove()
public E remove(int index) {
//越界檢查
rangeCheck(index);
modCount++;
//取出元素
E oldValue = elementData(index);
//拷貝數(shù)組,將 index 之后的元素往前移動(dòng)一個(gè)位置
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//最后一個(gè)元素置 null
elementData[--size] = null;
return oldValue;
}
remove(Object o)
刪除指定的元素,需要循環(huán)數(shù)組刪除第一個(gè)指定的元素。平均時(shí)間復(fù)雜度為 O(n)。
//ArrayList.remove(Object o)
public boolean remove(Object o) {
if (o == null) {
//循環(huán)整個(gè)數(shù)組,找出第一個(gè)需要?jiǎng)h除的元素
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
//循環(huán)整個(gè)數(shù)組,找出第一個(gè)需要?jiǎng)h除的元素
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
//ArrayList.fastRemove
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;
總結(jié)
- ArrayList 內(nèi)部用一個(gè)數(shù)組存儲(chǔ)元素,容量不夠時(shí)會(huì)擴(kuò)容原來的一半。
- ArrayList 實(shí)現(xiàn)了 RandomAccess,支持隨機(jī)訪問。
- ArrayList 實(shí)現(xiàn)了 Cloneable,支持被拷貝克隆。
- ArrayList 刪除指定元素和指定位置上的元素的效率不高,需要遍歷數(shù)組。
-
存儲(chǔ)
+關(guān)注
關(guān)注
13文章
4531瀏覽量
87442 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4380瀏覽量
64853 -
數(shù)組
+關(guān)注
關(guān)注
1文章
420瀏覽量
26540
發(fā)布評(píng)論請(qǐng)先 登錄
OpenHarmony語言基礎(chǔ)類庫【@ohos.util.ArrayList (線性容器ArrayList)】

FPGA與VHDL快速工程實(shí)踐從入門到提高
基于實(shí)踐的LabVIEW零基礎(chǔ)入門視頻教程---·10 中級(jí)計(jì)算器制作(三)
【學(xué)習(xí)打卡】OpenHarmony的ArrayList介紹
OpenHarmony應(yīng)用示例:線性容器 ArrayList
C語言程序實(shí)踐--ACM入門

圖靈程序設(shè)計(jì)叢書《Python編程:從入門到實(shí)踐》
JDK中java.util.ArrayList 類的介紹

鴻蒙語言基礎(chǔ)類庫:ohos.util.ArrayList 線性容器ArrayList

評(píng)論