Vue+Ant design vue安裝及配置使用
阿新 • • 發佈:2020-11-25
ArrayList原始碼分析
底層資料結構:Object型別陣列:Object[ ] elementData
一、JDK 7主體原始碼
步驟及其原始碼底層實現
1.建立一個ArrayList物件
ArrayList list = new ArrayList(); //底層建立了長度是10的Object[] 陣列elementData
底層實現:ArrayList.java
private transient Object[] elementData;
第一步:呼叫無參構造器
public ArrayList() { this.(initialCapacity:10); //呼叫本類當中的過載構造器 }
第二步:this.(initialCapacity:10);呼叫本類當中的過載構造器
public ArrayList(int initialCapacity) { super(); if(initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity] //初始化陣列,容量為10 }
2.新增資料,add()方法
list.add(1);
...
list.add(11); //elementData[0] = new Integer(1)
//如果此次的新增導致底層elementData陣列容量不夠,則擴容。
//預設情況下,擴容為原來的容量的1.5倍,同時需要將原有陣列中的資料複製到新的陣列中
底層實現:ArrayList.java
第一步:呼叫add( )
public boolean add(E e) { ensureCapacityInternal(size + 1); //確認容量是否夠 size:代表已經添加了幾個,初次為0 elementData[size++] = e; //新增操作 return true; }
第二步:呼叫ensureCapacityInternal(),確認容量是否夠
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0) //minCapacity即size + 1,elementData.length為10
grow(minCapacity); //擴容
}
- 擴容:當新增第11個元素時,size為10,size+1也就是minCapacity為11,此時if條件:minCapacity - elementData.length > 0
成立,於是呼叫grow()方法進行擴容。
grow()
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //初始容量:10
int newCapacity = oldCapacity + (oldCapacity >> 1); //預設擴容為原來的1.5倍,第一次擴容為15
...
elementData = Arrays.copyOf(elementData, newCapacity);
}
elementData = Arrays.copyOf(elementData, newCapacity);
原來容量為10的陣列elementData需要被重新賦值為容量為15的陣列,並且將原來的陣列元素複製到新陣列中
結論
建議開發中使用帶參構造器ArrayList arrayList = new ArrayList(int capacity);這樣可以避免擴容。
二、JDK 8中ArrayList的變化
1.建立一個ArrayList物件(沒有建立長度是10的Object[] 陣列)
ArrayList list = new ArrayList(); //底層Object[] elementData初始化為{},並沒有建立長度為10的陣列
底層實現:ArrayList.java
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //指定了一個常量
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //這裡什麼都沒有 長度為0
這裡不像JDK 7那樣在建立物件時就將陣列例項化,從時間和佔用記憶體(節省)上來說,這種方式較好一些
2.新增資料,add()方法
list.add(1) //第一次呼叫add()時,底層才建立了長度為10的陣列,並將資料1新增到elementData[0]
...
底層實現:ArrayList.java
第一步:第一次呼叫add( )
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
第二步:呼叫ensureCapacityInternal(),確認容量是否夠
0private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
第三步:呼叫calculateCapacity()
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //第一次呼叫add()時,該條件成立
return Math.max(DEFAULT_CAPACITY, minCapacity); //預設容量DEFAULT_CAPACITY為10
} //minCapacity即size+1=1
return minCapacity; //10
}
第四步:呼叫ensureExplicitCapacity()
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0) //minCapacity:10 elementData.length:0
grow(minCapacity); //10
}
第五步:呼叫grow()
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //0
int newCapacity = oldCapacity + (oldCapacity >> 1); //0=0+0
if (newCapacity - minCapacity < 0) //0-10<0
newCapacity = minCapacity; //newCapacity為10
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //此時建立了長度為10的陣列
}
三、總結
ArrayList原始碼分析:
1.jdk 7
ArrayList list = new ArrayList();
- 底層建立了長度是10的Object[] 陣列elementData。
list.add(1);
...
list.add(11); //elementData[0] = new Integer(1)
- list.add(11); --->如果此次的新增導致底層elementData陣列容量不夠,則擴容。預設情況下,擴容為原來的容量的1.5倍,同時需要將原有陣列中的資料複製到新的陣列中。
2.jdk 8中ArrayList的變化
ArrayList list = new ArrayList();
- 底層Object[] elementData初始化為{},並沒有建立長度為10的陣列
list.add(1)
...
- 第一次呼叫add()時,底層才建立了長度為10的陣列,並將資料1新增到elementData[0]。
- 後續的新增和擴容操作與jdk 7無異。
小結 |
---|
jdk 7當中的ArrayList的物件的建立類似單例的餓漢式,而jdk 8中的ArrayList的物件的建立類似於單例的懶漢式,延遲了陣列的創 |
建,節省記憶體。 |