在 Java 的 ArrayList 中,當(dāng)數(shù)組的容量不足以存儲新元素時,會觸發(fā)擴容操作。ArrayList 的底層使用數(shù)組來存儲元素,而擴容機制主要涉及到創(chuàng)建一個更大的數(shù)組,并將現(xiàn)有元素復(fù)制到新數(shù)組中。ArrayList 支持無參擴容和有參擴容兩種機制。
無參擴容機制:
無參擴容是指首次的擴容大小是10,后面在元素數(shù)量達(dá)到容量上限時,ArrayList 會創(chuàng)建一個新的數(shù)組,其大小通常是原數(shù)組容量的1.5倍,并將原數(shù)組中的元素復(fù)制到新數(shù)組中。這個過程涉及到創(chuàng)建新數(shù)組、復(fù)制元素等步驟(copyOf方法)。
以下是無參擴容的源碼示例:
//第一步
public boolean add (E e){
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//第二步
private void ensureCapacityInternal ( int minCapacity){ ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//第三步
private static int calculateCapacity (Object[]elementData,int minCapacity){
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}//DEFAULT_CAPACITY為10
return 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);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
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);
}
有參擴容機制:
有參擴容是指允許開發(fā)者在添加元素時指定擴容的大小。通過傳遞一個整數(shù)作為參數(shù),ArrayList 會根據(jù)指定的擴容大小進(jìn)行數(shù)組的擴容。后面在元素數(shù)量達(dá)到容量上限時,ArrayList 會創(chuàng)建一個新的數(shù)組,其大小通常是原數(shù)組容量的1.5倍。
有參擴容的源碼示例:
//第一步
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);
}
}
//第二步
private void ensureCapacityInternal ( int minCapacity){ ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//第三步
private static int calculateCapacity (Object[]elementData,int minCapacity){
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}//DEFAULT_CAPACITY為10
return 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);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
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);
}
java.util.Vector 是 Java 中的一種動態(tài)數(shù)組實現(xiàn),與 ArrayList 類似,它也支持無參擴容和有參擴容機制。Vector 是線程安全的,但在多線程環(huán)境下性能較差,已經(jīng)不太推薦使用。
無參擴容機制:
無參擴容是指首次的擴容大小默認(rèn)是10,后面在元素數(shù)量達(dá)到容量上限時,Vector 會創(chuàng)建一個新的數(shù)組,其大小通常是原數(shù)組容量的2倍,并將原數(shù)組中的元素復(fù)制到新數(shù)組中。這個過程涉及到創(chuàng)建新數(shù)組、復(fù)制元素等步驟(copyOf方法)。
以下是無參擴容的源碼示例:
//第一步
public Vector() {
this(10);
}
//第二步
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
//第三步
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
//第四步
private void ensureCapacityHelper(int minCapacity) {
// 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 + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
有參擴容機制:
有參擴容是指允許開發(fā)者在添加元素時指定擴容的大小。通過傳遞一個整數(shù)作為參數(shù),Vector 會根據(jù)指定的擴容大小進(jìn)行數(shù)組的擴容。后面在元素數(shù)量達(dá)到容量上限時,Vector 會創(chuàng)建一個新的數(shù)組,其大小通常是原數(shù)組容量的2倍。
有參擴容的源碼示例:
//第一步
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
//第二步
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
//第三步
protected AbstractList() {
}
//第四步
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
//第五步
private void ensureCapacityHelper(int minCapacity) {
// 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 + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
小結(jié):ArrayList
和 Vector
都是 Java 集合框架中動態(tài)數(shù)組的實現(xiàn),它們在很多方面非常相似,但也有一些關(guān)鍵的區(qū)別。在選擇使用哪個類時,需要考慮到它們的性能、線程安全性和適用場景等因素。
ArrayList 和 Vector 的對比:
-
線程安全性:
-
ArrayList
:不是線程安全的,多個線程同時訪問和修改ArrayList
可能會導(dǎo)致并發(fā)問題。 -
Vector
:是線程安全的,內(nèi)部使用同步機制來確保多線程下的安全訪問。
-
-
性能:
-
ArrayList
:由于不需要進(jìn)行額外的同步操作,相對于Vector
在單線程環(huán)境下性能更好。 -
Vector
:由于需要進(jìn)行同步操作,性能相對較差。在多線程環(huán)境下,由于同步開銷,可能也比ArrayList
性能較差。
-
-
擴容機制:
-
ArrayList
和Vector
的擴容機制類似,但ArrayList
可以通過構(gòu)造函數(shù)ArrayList(int initialCapacity)
或ensureCapacity(int minCapacity)
方法來設(shè)置初始容量,而Vector
只能通過構(gòu)造函數(shù)來設(shè)置初始容量。
-
-
適用場景:
- 如果在單線程環(huán)境下使用,且不需要線程安全性,推薦使用
ArrayList
。 - 如果在多線程環(huán)境下使用,或者需要考慮線程安全性,可以考慮使用
Vector
。但請注意,現(xiàn)代 Java 中更傾向于使用并發(fā)集合(如ConcurrentHashMap
、CopyOnWriteArrayList
等)來實現(xiàn)更高效的線程安全。
- 如果在單線程環(huán)境下使用,且不需要線程安全性,推薦使用
如何選擇:
-
性能要求:如果性能是首要考慮因素,且在單線程環(huán)境下使用,選擇
ArrayList
。如果線程安全性更重要,可以考慮使用其他線程安全的集合,而不是Vector
。 -
線程安全性:如果需要在線程之間共享數(shù)據(jù),或者在多線程環(huán)境下使用,而且沒有更好的線程安全替代品,可以考慮使用
Vector
。但要知道Vector
的性能會受到影響。 -
現(xiàn)代替代品:在現(xiàn)代 Java 中,還有更適合多線程環(huán)境的集合實現(xiàn),如
CopyOnWriteArrayList
或并發(fā)集合框架。這些集合能夠提供更好的性能和線程安全性。文章來源:http://www.zghlxwxcb.cn/news/detail-670120.html
綜上所述,除非有特定的需求,現(xiàn)代 Java 中更傾向于使用其他集合實現(xiàn),而不是直接使用 Vector
。在選擇時,需要根據(jù)具體的需求和環(huán)境來權(quán)衡性能和線程安全性。文章來源地址http://www.zghlxwxcb.cn/news/detail-670120.html
到了這里,關(guān)于Java中ArrayList的底層擴容機制和Vector的底層擴容機制,以及ArrayList和Vector的對比與選擇。附源碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!