CodeGym /課程 /JAVA 25 SELF /List:ArrayList 與 LinkedList,基本操作

List:ArrayList 與 LinkedList,基本操作

JAVA 25 SELF
等級 26 , 課堂 1
開放

1. 類別 ArrayList

在 Java 中,介面 List 是一份契約:「我是有序的元素集合,並且可以依據編號(索引)取得元素」。

清單(List)的關鍵特性:

  • 元素會以特定順序儲存(不同於 Set)。
  • 允許重複元素(例如:可以出現兩次 "Vasya")。
  • 可依索引存取元素:第一個元素索引為 0,第二個為 1,以此類推。
  • 可在清單的任意位置新增或刪除元素。

介面 List 最常見的實作是 ArrayList。其底層使用一般陣列,並會隨資料成長自動擴充。

如何建立 ArrayList

import java.util.ArrayList;
import java.util.List;

public class Example {
    public static void main(String[] args) {
        // 建立字串清單
        List<String> students = new ArrayList<>();
    }
}

說明

  • List<String> 是「字串清單」型別的變數。以介面宣告變數,而以具體類別(ArrayList)建立物件。
  • 尖括號 <String> 指定清單中元素的型別(泛型,generics)。

ArrayList(及任何 List)的主要方法:

  • add(element) — 將元素加入清單末尾。
  • add(index, element) — 在指定索引插入元素。
  • get(index) — 依索引取得元素。
  • set(index, element) — 依索引替換元素。
  • remove(index) — 依索引刪除元素。
  • remove(Object) — 刪除第一個與指定物件相等的元素。
  • size() — 取得清單的元素數量。

範例:操作學生清單

import java.util.ArrayList;
import java.util.List;

public class StudentListDemo {
    public static void main(String[] args) {
        List<String> students = new ArrayList<>();

        // 新增學生
        students.add("Vasya");
        students.add("Petya");
        students.add("Masha");

        // 輸出所有學生
        System.out.println("學生清單:" + students);

        // 取得第一位學生
        String first = students.get(0);
        System.out.println("第一位學生:" + first);

        // 修改第二位學生的名字
        students.set(1, "Pavel");
        System.out.println("修改後:" + students);

        // 刪除 Masha
        students.remove("Masha");
        System.out.println("刪除 Masha 之後:" + students);

        // 清單大小
        System.out.println("學生總數:" + students.size());
    }
}

輸出結果:

學生清單:[Vasya, Petya, Masha]
第一位學生:Vasya
修改後:[Vasya, Pavel, Masha]
刪除 Masha 之後:[Vasya, Pavel]
學生總數:2

這和我們的應用程式有何關聯?
假設我們有一個學生任務管理的應用程式。現在可以將任務清單以 List<String> 儲存(而非陣列),並可動態新增新任務。

2. 類別 LinkedList:當插入與刪除速度很重要

LinkedList 是另一種清單實作。其結構是雙向連結串列:每個節點都知道前一個與下一個元素。就像火車車廂:在中間插入一節「車廂」很快,無需重排整列車。

建立 LinkedList

import java.util.LinkedList;
import java.util.List;

public class Example {
    public static void main(String[] args) {
        List<String> tasks = new LinkedList<>();
    }
}

LinkedList 的特性

  • 在清單開頭與中間的插入與刪除很快。
  • 按索引存取較慢(要找到第 100 個元素,必須沿鏈逐一走訪)。
  • 適合經常不只在末尾,還會在開頭或中間新增/刪除元素的情況。

範例:使用 LinkedList

import java.util.LinkedList;
import java.util.List;

public class TaskListDemo {
    public static void main(String[] args) {
        List<String> tasks = new LinkedList<>();

        tasks.add("醒來");
        tasks.add("吃早餐");
        tasks.add("去上課");

        // 在開頭加入任務
        tasks.add(0, "設置鬧鐘");

        System.out.println("任務清單:" + tasks);

        // 刪除第一個任務(最早的)
        tasks.remove(0);

        System.out.println("刪除第一個任務之後:" + tasks);
    }
}

3. ArrayListLinkedList 的比較

準則
ArrayList
LinkedList
底層結構 陣列 雙向連結串列
按索引的快速存取 是 (O(1)) 否 (O(n))
在開頭/中間的快速插入/刪除 否 (O(n)) 是 (O(1) — 若已持有節點參考)
在末尾的快速插入/刪除 是(通常為 O(1)) 是 (O(1))
記憶體 占用較少記憶體 較多(需額外儲存前後節點的參考)
典型場景 經常按索引存取 頻繁插入/刪除

簡單規則:

  • 需要依索引快速存取時 — 使用 ArrayList
  • 經常在開頭或中間新增/刪除時 — 使用 LinkedList

4. 清單的常見操作

遍歷清單元素

一般 for 迴圈

for (int i = 0; i < students.size(); i++) {
    System.out.println("學生 #" + i + ": " + students.get(i));
}

for-each 迴圈(最常用的方法)

for (String name : students) {
    System.out.println("姓名:" + name);
}

Lambda 運算式(Java 8+)

students.forEach(name -> System.out.println("姓名:" + name));

查找元素

  • contains(element) — 若元素存在於清單中則回傳 true
  • indexOf(element) — 回傳元素第一次出現的索引;若找不到則為 -1
if (students.contains("Vasya")) {
    System.out.println("Vasya 在清單中!");
}
int index = students.indexOf("Vasya");
System.out.println("Vasya 的索引:" + index);

清空清單

clear() — 刪除所有元素。

students.clear();
System.out.println("清空後的清單:" + students);

5. 什麼時候用 ArrayList,什麼時候用 LinkedList

可以這麼想:ArrayList 適用於需要依索引快速存取,且清單變動不頻繁的情境。例如果很長的使用者清單或訊息歷史——主要以讀取為主。

相反地,LinkedList 適合在開頭/中間經常插入或刪除元素。這可能是佇列、堆疊或復原(撤銷)歷史。

實務上最常用的是 ArrayList。而 LinkedList 比較像是「備用工具」:平時放在工具箱裡,但偶爾剛好派上用場。

6. 操作清單時的常見錯誤

錯誤 1:索引越界。 最常見的情況是以不存在的索引存取元素。若清單只有三個元素,卻呼叫 students.get(5),會拋出 IndexOutOfBoundsException。在存取前請先檢查 size()

錯誤 2:遍歷時刪除元素。for-each 遍歷並同時刪除元素會導致 ConcurrentModificationException。若要進行複雜的刪除,請使用索引迴圈或 Iterator

錯誤 3:不正確的物件比較。 若你儲存的是自訂物件(例如 Student),containsremove 會依賴 equals。如果沒有覆寫它,比較將會以參考為準,而非內容。

錯誤 4:使用 raw type。 不要寫 List list = new ArrayList() —— 一定要標明元素型別:List<String> list = new ArrayList<>()。泛型能避免錯誤並讓程式碼更清晰。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION