Java-ArrayList
阿新 • • 發佈:2021-10-16
ArrayList(部分內容摘取於:優秀參考文章)
【介紹】
ArrayList就是動態陣列,用MSDN中的說法,就是Array的複雜版本,它提供了動態的增加和減少元素,實現了ICollection和IList介面,靈活的設定陣列的大小等好處
ArrayList封裝了一系列操作,如增刪改查,對比使用傳統的陣列方便了很多,因為java程式碼已經替我們寫好了,我們直接用即可。
【使用】
一、構造方法:
(1)無參構造器:返回一個初始容量為0的空列表,擴容是在第一次add的時候進行的
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
(2)傳入一個 int型別
的有參構造器:返回一個以你傳入的引數作為初始容量的空列表
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); } }
(3)構造一個包含指定 collection 的元素的列表,這些元素是按照該 collection 的迭代器返回它們的順序排列的。
public ArrayList(Collection<? extends E> c) { Object[] a = c.toArray(); if ((size = a.length) != 0) { if (c.getClass() == ArrayList.class) { elementData = a; } else { elementData = Arrays.copyOf(a, size, Object[].class); } } else { // replace with empty array. elementData = EMPTY_ELEMENTDATA; } }
二、常用方法:
以實現List介面為例:
【底層操作機制原始碼分析】
(1)ArrayList中維護了一個Object型別的陣列 elementData
(2)當建立ArrayList物件時,如果使用的是無參構造器,則初始elementData容量為0,第一次add,則擴容為10,如果後續再次需要擴容,則擴容為原容量的1.5倍(看原始碼,有移位操作)
(3)如果使用的是指定大小的構造器,則初始容量為指定的大小,如果後續需要擴容,則擴容為1.5倍。
ArrayList類的相關方法和屬性:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
//無參構造器:elementData被賦值為一個空的物件陣列
}
transient Object[] elementData; //transient(短暫的意思):對於transient 修飾的成員變數,在類的例項物件的序列化處理過程中會被忽略。
private static final int DEFAULT_CAPACITY = 10; //欄位意思:預設容量,值為10
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //就是一個空的物件陣列
private int size; //初始值為0
無參構造器第一次 add:
public boolean add(E e) {
modCount++; //該欄位表示list結構上被修改的次數
add(e, elementData, size);
return true;
}
private void add(E e, Object[] elementData, int s) {
//判斷元素個數 size 是否等於陣列elementData的長度,如果相等,則進行擴容操作
if (s == elementData.length) //s=size=初始值0;elementData陣列一開始也是空陣列,長度為0
elementData = grow();
elementData[s] = e; //將元素新增進陣列中
size = s + 1; //新增完成後,size加1
}
private Object[] grow() {
return grow(size + 1); //傳入size + 1 = 0+1 = 1
}
private Object[] grow(int minCapacity) { //最小容量為 1(size + 1)
int oldCapacity = elementData.length; //舊容量為空陣列長度0
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //第一次add,這裡都是fasle,進入else
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else { //返回一個新的物件陣列給elementData,容量是DEFAULT_CAPACITY, minCapacity這兩個的最大值,故第一次擴容,容量是10
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
無參構造器第十一次add:
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// assert oldLength >= 0
// assert minGrowth > 0
int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
if (newLength - MAX_ARRAY_LENGTH <= 0) {
return newLength;
}
return hugeLength(oldLength, minGrowth);
}
有參構造器:
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);
}
}
注意使用有參構造器傳入引數0和使用無參構造器的區別:
//它們的擴容機制不太一樣
List list2 = new ArrayList(0); //this.elementData = EMPTY_ELEMENTDATA;
List list3 = new ArrayList(); //this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
擴容方法:(Arrays.copyOf()方法詳解-jdk1.8)
return elementData = Arrays.copyOf(elementData, newCapacity);
modCount引數:
參考文章:https://blog.csdn.net/u012926924/article/details/50452411