Java 列表接口
一、概述
在本教程中,我們將了解 Java List
接口。我們將討論List
提供的方法、其實現和使用場景。
2. Java 列表介紹
Java 是一種面向對象的語言,因此大多數問題都涉及對像以及與這些對象相關聯的行為或動作。
此外,我們經常需要同時操作多個相同類型的對象,這就是集合發揮作用的地方。 Java List
是保證元素順序並允許重複的集合的實現。
3.列出方法和用法
讓我們看一下List
接口中最重要的方法,看看我們如何使用它們。對於此示例,我們將使用ArrayList
實現。
3.1.添加元素
讓我們使用void add(E element)
方法向列表中添加新元素:
@Test
public void givenAFruitList_whenAddNewFruit_thenFruitIsAdded(){
List fruits = new ArrayList();
assertEquals("Unexpected number of fruits in the list, should have been 0", 0, fruits.size());
fruits.add("Apple");
assertEquals("Unexpected number of fruits in the list, should have been 1", 1, fruits.size());
}
3.2.檢查列表是否包含元素
我們可以使用boolean contains(Object o)
方法檢查列表是否包含元素:
@Test
public void givenAFruitList_whenContainsFruit_thenFruitIsInTheList(){
List fruits = new ArrayList();
fruits.add("Apple");
assertTrue("Apple should be in the fruit list", fruits.contains("Apple"));
assertFalse("Banana should not be in the fruit list", fruits.contains("Banana"));
}
3.3.檢查列表是否為空
讓我們使用boolean isEmpty()
方法檢查列表是否為空:
@Test
public void givenAnEmptyFruitList_whenEmptyCheck_thenListIsEmpty(){
List fruits = new ArrayList();
assertTrue("Fruit list should be empty", fruits.isEmpty());
fruits.add("Apple");
assertFalse("Fruit list should not be empty", fruits.isEmpty());
}
3.4.迭代列表
如果我們想遍歷列表,我們可以使用方法ListIterator listIterator()
:
@Test
public void givenAFruitList_whenIterateOverIt_thenFruitsAreInOrder(){
List fruits = new ArrayList();
fruits.add("Apple"); // fruit at index 0
fruits.add("Orange");// fruit at index 1
fruits.add("Banana");// fruit at index 2
int index = 0;
for (Iterator it = fruits.listIterator(); it.hasNext(); ) {
String fruit = it.next();
assertEquals("Fruits should be in order", fruits.get(index++), fruit);
}
}
3.5.刪除元素
讓我們使用方法boolean remove(Object o)
從列表中刪除一個元素:
@Test
public void givenAFruitList_whenRemoveFruit_thenFruitIsRemoved(){
List fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Orange");
assertEquals("Unexpected number of fruits in the list, should have been 2", 2, fruits.size());
fruits.remove("Apple");
assertEquals("Unexpected number of fruits in the list, should have been 1", 1, fruits.size());
}
3.6.修改元素
讓我們使用方法E set(int index, E element)
修改指定索引處的列表元素:
@Test
public void givenAFruitList_whenSetFruit_thenFruitIsUpdated(){
List fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Orange");
fruits.set(0, "Banana");
assertEquals("Fruit at index 0 should be Banana", "Banana", fruits.get(0));
}
3.7.獲取列表大小
讓我們使用方法int size()
檢索列表的大小:
List fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Orange");
assertEquals("Unexpected number of fruits in the list, should have been 2", 2, fruits.size());
3.8.排序列表
我們有很多方法對列表進行排序。在這裡,讓我們看看如何使用List
接口中的方法default void sort(Comparator c)
來完成它。
該方法需要一個比較器作為參數。讓我們為它提供自然順序比較器:
@Test
public void givenAFruitList_whenSort_thenFruitsAreSorted(){
List fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Orange");
fruits.add("Banana");
fruits.sort(Comparator.naturalOrder());
assertEquals("Fruit at index 0 should be Apple", "Apple", fruits.get(0));
assertEquals("Fruit at index 1 should be Banana", "Banana", fruits.get(1));
assertEquals("Fruit at index 2 should be Orange", "Orange", fruits.get(2));
}
3.9.創建子列表
我們可以通過向方法List subList(int fromIndex, int toIndex).
提供fromIndex
和toIndex
參數來從列表創建子列表。我們需要在這裡考慮toIndex
是不包含的:
@Test
public void givenAFruitList_whenSublist_thenWeGetASublist(){
List fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Orange");
fruits.add("Banana");
List fruitsSublist = fruits.subList(0, 2);
assertEquals("Unexpected number of fruits in the sublist, should have been 2", 2, fruitsSublist.size());
assertEquals("Fruit at index 0 should be Apple", "Apple", fruitsSublist.get(0));
assertEquals("Fruit at index 1 should be Orange", "Orange", fruitsSublist.get(1));
}
3.10.使用列表元素創建數組
我們可以使用方法T[] toArray(T[] a)
創建一個包含列表元素的數組:
@Test
public void givenAFruitList_whenToArray_thenWeGetAnArray(){
List fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Orange");
fruits.add("Banana");
String[] fruitsArray = fruits.toArray(new String[0]);
assertEquals("Unexpected number of fruits in the array, should have been 3", 3, fruitsArray.length);
assertEquals("Fruit at index 0 should be Apple", "Apple", fruitsArray[0]);
assertEquals("Fruit at index 1 should be Orange", "Orange", fruitsArray[1]);
assertEquals("Fruit at index 2 should be Banana", "Banana", fruitsArray[2]);
}
4. List
實現
讓我們看一下List
接口在 Java 中最常用的實現。
4.1. ArrayList
ArrayList
是List
接口的可調整大小的數組實現。它實現所有可選操作並允許所有元素,包括null
。這個類大致等同於Vector
,除了它是不同步的。
這是List
接口使用最廣泛的實現。
4.2. CopyOnWriteArrayList
CopyOnWriteArrayList
是ArrayList
的線程安全變體。此類中的所有可變操作(添加、設置等)都會創建底層數組的新副本。
此實現用於其固有的線程安全功能。
4.3. LinkedList
LinkedList
是List
和Deque
接口的雙向鍊錶實現。它實現所有可選操作並允許所有元素(包括null
)。
4.4.抽象列表實現
我們這裡有兩個抽象實現,它們提供了List
接口的骨架實現。這些有助於最大限度地減少擴展和自定義List
所需的工作:
-
AbstractList
為其內部狀態保留一個“隨機訪問”數據存儲(例如數組) -
AbstractSequentialList
為其內部狀態保留一個“順序訪問”數據存儲(例如鍊表)
4.5.其他具體列表實現
這裡有兩個更具體的實現值得討論:
-
Vector
實現一個可增長的對像數組。也像數組一樣,它包含可以使用整數索引訪問的組件。這個類是同步的。因此,如果不需要線程安全的實現,建議使用ArrayList
代替Vector
。 -
Stack
– 表示對象的後進先出 (LIFO) 堆棧。它擴展了類Vector
並提供了五個額外的操作,允許將向量視為堆棧。
Java 還提供了幾個特定的List
實現,它們的行為類似於上面討論的實現之一。
5.結論
在本文中,我們探討了 Java List
接口及其實現。當我們只關心元素順序並允許重複時,列表是首選集合類型。由於它們在內部處理增長,因此比數組更受歡迎。
和往常一樣,可以在 GitHub 上找到代碼片段。