Java ArrayList

ArrayList 是最常用的 List 實作,基於動態陣列,支援隨機存取。

建立 ArrayList

import java.util.ArrayList;

// 空的 ArrayList
ArrayList<String> list1 = new ArrayList<>();

// 指定初始容量
ArrayList<String> list2 = new ArrayList<>(100);

// 從其他集合建立
ArrayList<String> list3 = new ArrayList<>(Arrays.asList("A", "B", "C"));

// 使用 List 介面(推薦)
List<String> list4 = new ArrayList<>();

常用方法

新增元素

List<String> list = new ArrayList<>();

list.add("Apple");           // 加到尾端
list.add("Banana");
list.add(0, "First");        // 插入到指定位置
list.addAll(Arrays.asList("C", "D"));  // 加入多個

存取元素

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

String first = list.get(0);      // "A"
String last = list.get(list.size() - 1);  // "C"

int index = list.indexOf("B");   // 1
int lastIndex = list.lastIndexOf("B");

修改元素

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

list.set(1, "X");  // 將索引 1 的元素改為 "X"
// ["A", "X", "C"]

刪除元素

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "B"));

list.remove(0);        // 刪除索引 0 的元素
list.remove("B");      // 刪除第一個 "B"
list.clear();          // 清空

// 刪除多個
list.removeAll(Arrays.asList("A", "B"));

// 條件刪除
list.removeIf(s -> s.startsWith("A"));

檢查元素

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

boolean hasA = list.contains("A");  // true
boolean empty = list.isEmpty();     // false
int size = list.size();             // 3

遍歷

List<String> list = Arrays.asList("A", "B", "C");

// for 迴圈
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

// for-each
for (String s : list) {
    System.out.println(s);
}

// forEach + Lambda
list.forEach(s -> System.out.println(s));
list.forEach(System.out::println);

// Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

排序

List<Integer> numbers = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5));

// 升冪排序
Collections.sort(numbers);
// 或
numbers.sort(null);
// 或
numbers.sort(Comparator.naturalOrder());

// 降冪排序
Collections.sort(numbers, Collections.reverseOrder());
numbers.sort(Comparator.reverseOrder());

// 自訂排序
List<String> names = new ArrayList<>(Arrays.asList("Bob", "Alice", "Charlie"));
names.sort((a, b) -> a.length() - b.length());  // 依長度

轉換

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

// 轉為陣列
String[] array = list.toArray(new String[0]);

// 陣列轉 List
String[] arr = {"X", "Y", "Z"};
List<String> fromArray = new ArrayList<>(Arrays.asList(arr));

// 轉為 Stream
list.stream().filter(s -> s.equals("A")).collect(Collectors.toList());

子列表

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));

List<String> subList = list.subList(1, 4);  // ["B", "C", "D"]

// 注意:subList 是原列表的視圖
subList.set(0, "X");  // list 也會改變

效能特性

操作時間複雜度
get(index)O(1)
add(element)O(1) 攤平
add(index, element)O(n)
remove(index)O(n)
remove(element)O(n)
contains(element)O(n)

ArrayList vs LinkedList

特性ArrayListLinkedList
隨機存取O(1)O(n)
尾端插入O(1)O(1)
中間插入O(n)O(1)
記憶體較少較多

一般情況下優先使用 ArrayList。

注意事項

避免在遍歷時修改

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

// 錯誤:ConcurrentModificationException
// for (String s : list) {
//     list.remove(s);
// }

// 正確:使用 Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if (it.next().equals("B")) {
        it.remove();
    }
}

// 或使用 removeIf
list.removeIf(s -> s.equals("B"));

泛型

// 不建議:原始類型
ArrayList list = new ArrayList();

// 建議:使用泛型
ArrayList<String> list = new ArrayList<>();