在Java編程中,ArrayList
是一個非常常用的數據結構,它提供了動態數組的功能,可以根據需要自動調整大小。雖然Java標準庫中已經提供了ArrayList
的實現,但通過自己實現一個自定義的ArrayList
類,可以幫助我們更好地理解其內部工作原理,并提升我們的編程能力。
本文將詳細介紹如何從零開始實現一個自定義的ArrayList
類,涵蓋從基本設計到具體實現的各個方面。
ArrayList
是Java集合框架中的一部分,它基于動態數組實現。與普通數組不同,ArrayList
可以根據需要自動擴展其容量,從而避免了手動管理數組大小的麻煩。ArrayList
的主要特點包括:
ArrayList
會自動增加其容量。ArrayList
支持通過索引快速訪問元素。ArrayList
中是按照插入順序存儲的。在實現自定義ArrayList
類之前,我們需要明確其基本功能和結構。一個簡單的ArrayList
類應該至少包含以下功能:
為了實現這些功能,我們需要定義一個類,并在其中維護一個數組來存儲元素。此外,我們還需要記錄當前列表的大小和容量。
首先,我們定義一個名為CustomArrayList
的類,并在其中聲明必要的成員變量:
public class CustomArrayList<E> {
private static final int DEFAULT_CAPACITY = 10; // 默認初始容量
private Object[] elements; // 存儲元素的數組
private int size; // 當前列表大小
// 構造函數
public CustomArrayList() {
elements = new Object[DEFAULT_CAPACITY];
size = 0;
}
}
在這個類中,我們使用了一個Object
類型的數組elements
來存儲元素。由于Java的泛型在運行時會被擦除,因此我們使用Object
數組來存儲任意類型的元素。size
變量用于記錄當前列表中元素的數量。
我們已經在類中定義了一個無參構造函數,它將數組的初始容量設置為DEFAULT_CAPACITY
(默認為10)。此外,我們還可以提供一個帶有初始容量參數的構造函數,以便用戶可以根據需要指定初始容量:
public CustomArrayList(int initialCapacity) {
if (initialCapacity > 0) {
elements = new Object[initialCapacity];
} else if (initialCapacity == 0) {
elements = new Object[DEFAULT_CAPACITY];
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
size = 0;
}
add
方法用于在列表末尾添加元素。如果當前數組已滿,我們需要先擴展數組的容量,然后再添加元素。以下是add
方法的實現:
public void add(E element) {
if (size == elements.length) {
ensureCapacity(size + 1); // 確保容量足夠
}
elements[size++] = element;
}
在這個方法中,我們首先檢查當前數組是否已滿。如果已滿,則調用ensureCapacity
方法擴展數組容量。然后,我們將新元素添加到數組的末尾,并增加size
的值。
get
方法用于通過索引獲取元素。我們需要確保索引在有效范圍內,然后返回對應位置的元素:
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
return (E) elements[index];
}
在這個方法中,我們首先檢查索引是否有效。如果索引超出范圍,則拋出IndexOutOfBoundsException
異常。否則,我們返回對應位置的元素,并將其強制轉換為泛型類型E
。
remove
方法用于通過索引刪除元素。刪除元素后,我們需要將后續元素向前移動,以填補刪除后的空缺:
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
E removedElement = (E) elements[index];
int numMoved = size - index - 1;
if (numMoved > 0) {
System.arraycopy(elements, index + 1, elements, index, numMoved);
}
elements[--size] = null; // 清除最后一個元素的引用
return removedElement;
}
在這個方法中,我們首先檢查索引是否有效。然后,我們獲取要刪除的元素,并將后續元素向前移動。最后,我們將最后一個元素的引用設置為null
,并減少size
的值。
size
方法用于返回當前列表中元素的數量:
public int size() {
return size;
}
這個方法非常簡單,直接返回size
變量的值即可。
當列表容量不足時,我們需要擴展數組的容量。通常,我們會將數組的容量擴展為當前容量的1.5倍。以下是ensureCapacity
方法的實現:
private void ensureCapacity(int minCapacity) {
int oldCapacity = elements.length;
if (minCapacity > oldCapacity) {
int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量為舊容量的1.5倍
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
elements = Arrays.copyOf(elements, newCapacity);
}
}
在這個方法中,我們首先計算新的容量。如果新容量仍然小于所需的最小容量,則將新容量設置為最小容量。然后,我們使用Arrays.copyOf
方法將舊數組復制到新數組中。
為了方便調試和輸出,我們可以重寫toString
方法,使其返回列表中所有元素的字符串表示:
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
for (int i = 0; i < size; i++) {
sb.append(elements[i]);
if (i < size - 1) {
sb.append(", ");
}
}
sb.append(']');
return sb.toString();
}
在這個方法中,我們使用StringBuilder
來構建字符串表示。我們遍歷數組中的元素,并將它們添加到StringBuilder
中,最后返回構建好的字符串。
為了驗證我們的自定義ArrayList
類的正確性,我們可以編寫一些測試代碼:
public class CustomArrayListTest {
public static void main(String[] args) {
CustomArrayList<String> list = new CustomArrayList<>();
// 添加元素
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 輸出列表
System.out.println("List: " + list);
// 獲取元素
System.out.println("Element at index 1: " + list.get(1));
// 刪除元素
list.remove(1);
System.out.println("List after removing element at index 1: " + list);
// 獲取列表大小
System.out.println("Size of list: " + list.size());
}
}
運行這個測試代碼,我們可以看到以下輸出:
List: [Apple, Banana, Cherry]
Element at index 1: Banana
List after removing element at index 1: [Apple, Cherry]
Size of list: 2
這個輸出表明我們的自定義ArrayList
類能夠正確地添加、獲取、刪除元素,并且能夠正確地返回列表的大小。
通過本文的介紹,我們詳細講解了如何從零開始實現一個自定義的ArrayList
類。我們從基本概念出發,逐步實現了添加、獲取、刪除元素等功能,并實現了動態擴容機制。最后,我們通過測試代碼驗證了自定義ArrayList
類的正確性。
通過自己實現ArrayList
類,我們不僅加深了對Java集合框架的理解,還提升了編程能力。希望本文能夠幫助你更好地掌握Java中的動態數組實現,并為你的編程學習提供有價值的參考。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。