1. 前言 Java 中 List 的重要性是什麼? 在 Java 程式設計中,「List」是經常出現的資料結構。特別是在需要一次管理多個值的情況下,由於它比陣列更靈活且易於使用,因此在許多實際應用中受到青睞。 「List」是 Java 集合框架的核心介面,通過 ArrayList、LinkedList 等各種實作類別,建構了能應對多樣化情境的機制。數據的建立、刪除、搜尋、更新等操作可以直覺地進行,這也是 List 受到支持的原因之一。本文的目的與目標讀者 本文將從基礎到應用,系統地、易於初學者理解的方式解說「Java List」 。主要針對以下讀者:剛開始學習 Java,對 List 的使用感到不安的人 想清楚理解陣列(Array)與 List 差異的人 正在煩惱如何區分使用 ArrayList 和 LinkedList 的人 想在實際工作中重新複習 List 基礎知識的人 希望讀完本文後,能確實掌握 Java 中 List 的基本概念、實作方法和具體操作,並能自信地進行程式編寫。 從下一章開始,將首先從「什麼是 List?」這個基本部分開始,依序進行說明。2. 什麼是 List? List 的概述與特點 在 Java 中,「List」是以順序保持元素的集合 介面。最大的特點是,元素的增加順序會被保留 ,並且可以使用索引(從 0 開始)來存取個別元素 。 List 作為集合框架的一部分提供,具有以下功能:允許元素重複 可以通過指定索引來獲取、更新、刪除元素 可以動態地增加或減少元素數量(與陣列不同,不是固定長度) 這使得數據操作更加靈活 ,在實際工作中也經常使用。與陣列(Array)的差異 在 Java 中,陣列(int[]、String[] 等)也作為存放多個值的方式存在,但與 List 有一些不同之處。比較項目 陣列(Array) List 元素數量變更 不可(固定長度) 可(可動態增減) 提供的功能 最少的操作(索引存取、獲取長度) 豐富的方法(add, remove, contains 等) 型別 可以處理基本型別 僅限物件型別(需要使用包裹類別) 型別安全性 陣列在編譯時進行型別檢查 可以使用泛型嚴格指定型別
因此,List 作為更靈活且功能更強大的集合 ,在許多情況下比陣列更具實用性。List 介面及其實作類別 在 Java 中使用 List 時,通常使用 List 介面來宣告變數,並使用具體類別(實作類別)來建立實例。代表性的實作類別如下:ArrayList 結構類似於陣列,可以實現高速存取。擅長數據搜尋和隨機存取。LinkedList 每個元素都與前後元素相連。插入和刪除速度快,適合經常進行操作的列表。Vector 類似於 ArrayList,但它是執行緒安全的,相對來說效率較低。目前較少使用。 一般來說,除非有特殊原因,否則ArrayList 是最常用的。您可以根據用途參考後面的效能比較來區分使用。3. List 的基本用法 本節將依序解說在 Java 中使用 List 的基本操作。這裡主要以ArrayList 為例,介紹 List 的代表性操作。List 的宣告與初始化 首先,是使用 ArrayList 對 List 進行基本宣告與初始化。import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
}
} 通常使用 List 介面宣告變數,並使用 ArrayList 建立實例。使用泛型指定要儲存的型別(這裡指定為 String)。元素的新增(add) 若要將元素新增至 List,請使用 add() 方法。fruits.add("りんご");
fruits.add("バナナ");
fruits.add("みかん"); 這樣,三個元素將依序新增到 List 中。List 會保留元素的增加順序 。元素的獲取(get) 若要獲取指定索引的元素,請使用 get(int index)。System.out.println(fruits.get(0)); // 「りんご」が表示される 請注意,索引是從 0 開始 。元素的更新(set) 若要更新某個位置的元素,請使用 set(int index, E element)。fruits.set(1, "ぶどう"); // 2番目の要素「バナナ」が「ぶどう」に置き換わる元素的刪除(remove) 也可以刪除特定索引或元素本身。fruits.remove(0); // 先頭の要素を削除
fruits.remove("みかん"); // 「みかん」を削除(最初に一致したものだけ)獲取 List 的大小(size) 可以使用 size() 方法獲取當前元素的數量。System.out.println(fruits.size()); // 2などが返る檢查元素是否存在(contains) 若要檢查 List 是否包含特定元素,請使用 contains()。if (fruits.contains("ぶどう")) {
System.out.println("ぶどうはあります");
}總結:常用基本操作一覽 操作 方法範例 說明 新增 add("元素")新增至最後 獲取 get(索引)元素的參考 更新 set(索引, 新元素)變更指定位置的元素 刪除 remove(索引/元素)刪除指定的元素 獲取大小 size()獲取元素數量 檢查存在 contains("元素")確認特定元素是否存在
4. List 的操作範例 本章將介紹使用 Java List 的實際操作範例。需要依序處理列表內元素的情況非常多,這裡將介紹使用for 迴圈、增強型 for 迴圈、Stream API 的代表性方法。使用 for 迴圈遍歷 最基本的方法是使用 for 迴圈,通過索引來取出元素。List<String> fruits = new ArrayList<>();
fruits.add("りんご");
fruits.add("バナナ");
fruits.add("みかん");
for (int i = 0; i < fruits.size(); i++) {
System.out.println(fruits.get(i));
} 這種方法可以進行精確的索引控制 。例如,在只想處理偶數位置的元素時非常有效。使用增強型 for 迴圈(for-each)遍歷 如果想不考慮索引,依序處理所有元素,那麼增強型 for 迴圈非常方便。for (String fruit : fruits) {
System.out.println(fruit);
} 寫法簡單易讀,是最常用的方法之一 。對於簡單的處理,這種方法足夠應付。使用 Lambda 表達式和 Stream API 遍歷 從 Java 8 開始,也可以使用 Stream API 和 Lambda 表達式進行編寫。fruits.stream().forEach(fruit -> System.out.println(fruit)); 這種寫法的優點是可以將多個處理串連起來 。例如,可以輕鬆地先根據特定條件過濾再輸出。fruits.stream()
.filter(fruit -> fruit.contains("ん"))
.forEach(System.out::println); 這個範例中,只輸出包含「ん」的水果。特別推薦給想習慣函數式風格編程的人 。各種方法的區分使用 方法 優點 適用場景 傳統 for 迴圈 可進行索引控制 需要元素編號的處理 增強型 for 迴圈 寫法簡單易讀 簡單的遍歷處理 Stream API 擅長條件式處理和連續處理 想組合過濾、映射、聚合等操作的情況
5. ArrayList 與 LinkedList 的差異與區分使用 作為實作 Java List 介面的代表性類別,有ArrayList 和LinkedList 。兩者都可以作為 List 使用,但由於內部結構和效能特性的差異,在適當的場合區分使用非常重要。ArrayList 的特點與適用用途 ArrayList 內部使用動態陣列(可變長度陣列) 。主要特點: 隨機存取(指定索引)速度非常快 若為列表末尾新增元素速度快(平均 O(1)) 中間插入或刪除會變慢(O(n)) 適用場景: 經常進行搜尋(get())的場景 元素數量可以在事前一定程度上預測的場景 元素新增和刪除較少,以讀取為主的處理 List<String> list = new ArrayList<>();LinkedList 的特點與適用用途 LinkedList 使用雙向連結列表的結構 實現。主要特點: 元素的新增和刪除速度快(特別是開頭或結尾) 隨機存取(get(index))速度慢(O(n)) 記憶體消耗量比 ArrayList 稍微多一些 適用場景: 經常進行元素插入和刪除的場景(特別是開頭或中間) 想作為佇列(Queue)或堆疊(Stack)使用時 以疊代為主,不需要索引存取的情況 List<String> list = new LinkedList<>();效能比較 下表顯示常用操作的理論計算複雜度(大 O 表示法) 。操作 ArrayList LinkedList get(int index)O(1) O(n) add(E e)(末尾)O(1) O(1) add(int index, E e)O(n) O(n) remove(int index)O(n) O(n) 疊代 O(n) O(n)
※ 實際處理時間也受到數據大小、JVM 優化等因素影響。實際應用中區分使用的重點 如果「將數據視為列表,並透過索引存取」,則使用 ArrayList 如果「經常在開頭或中間插入・刪除」,則使用 LinkedList 在效能要求嚴苛的處理中,務必進行基準測試並驗證 6. List 的進階用法 本節將介紹讓 Java List 使用更方便的進階技巧。List 不僅僅是數據的集合體,還可以通過排序、洗牌、過濾、轉換等方式進行多種處理 。List 的排序(Collections.sort) 使用 Collections.sort() 可以將 List 中的元素按升序排序 。元素需要實作 Comparable 介面。import java.util.*;
List<String> fruits = new ArrayList<>();
fruits.add("バナナ");
fruits.add("りんご");
fruits.add("みかん");
Collections.sort(fruits);
System.out.println(fruits); // [みかん, りんご, バナナ]以自訂順序排序時(使用 Comparator) fruits.sort(Comparator.reverseOrder()); // 降順に並び替えList 的洗牌(Collections.shuffle) 若要隨機打亂元素的順序,可以使用 Collections.shuffle()。Collections.shuffle(fruits);
System.out.println(fruits); // [バナナ, みかん, りんご](例) 在需要遊戲牌組或隨機顯示順序時很方便。使用 Stream API 過濾(filter) 使用 Java 8 開始的 Stream,可以簡潔地編寫只提取符合條件的元素 的處理。List<String> filtered = fruits.stream()
.filter(fruit -> fruit.contains("ん"))
.collect(Collectors.toList());
System.out.println(filtered); // [みかん, りんご]使用 Stream API 轉換(map) 若要將元素轉換為其他形式,請使用 map()。List<Integer> lengths = fruits.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println(lengths); // 各果物名の文字数 [3, 3, 2] などmap() 在數據的格式轉換和預處理 中是強大的工具。進階操作總結 操作 使用範例 主要用途 排序 Collections.sort(list)按升序排列 洗牌 Collections.shuffle(list)隨機打亂元素的順序 過濾 stream().filter(...).collect()只提取符合條件的元素 轉換 stream().map(...).collect()轉換元素的型別或值
7. 常見錯誤及其處理方法 在使用 Java List 時,初學者特別容易遇到的問題是「例外(錯誤)」。這裡將具體解說實際上經常發生的代表性錯誤、其原因和解決方法。IndexOutOfBoundsException(索引超出範圍錯誤) 發生原因: 嘗試存取不存在的索引時發生。List<String> list = new ArrayList<>();
list.add("りんご");
System.out.println(list.get(1)); // エラー:Index 1 out of bounds處理方法: 在存取前確認大小,或通過條件判斷來控制索引是否有效。if (list.size() > 1) {
System.out.println(list.get(1));
}NullPointerException(空指標例外) 發生原因: 在 List 本身或 List 的元素為 null 的狀態下呼叫方法時發生。List<String> list = null;
list.add("りんご"); // NullPointerException発生處理方法: 事先確認變數不是 null,或利用 Optional 等。 或者,注意不要忘記初始化:List<String> list = new ArrayList<>(); // 正しい初期化ConcurrentModificationException(並發修改例外) 發生原因: 在使用 for-each 迴圈或 Iterator 遍歷 List 時,直接修改 List 時發生。for (String fruit : list) {
if (fruit.equals("バナナ")) {
list.remove(fruit); // ConcurrentModificationException
}
}處理方法: 使用 Iterator 安全刪除,或使用 removeIf() 等方法。 或者,從 Java 8 開始可以更簡潔:list.removeIf(fruit -> fruit.equals("バナナ"));其他注意事項 僅宣告變數但未使用的情況非常多。初始化是必須的。 這是初學者常見的錯誤,容易誤以為「第一個是索引 1」。錯誤處理總結 錯誤名稱 主要原因 處理方法範例 IndexOutOfBoundsException 存取不存在的索引 使用 size() 確認長度 NullPointerException List 或元素為 null 不要忘記初始化,並進行 null 檢查 ConcurrentModificationException 遍歷期間直接修改 List 使用 Iterator 操作或利用 removeIf()
8. 總結 回顧 Java List 的基礎知識 本文循序漸進地解說了 Java 中 List 的基礎到應用。List 在 Java 集合中是使用頻率特別高的,是靈活處理數據的重要工具 。 首先,在掌握了什麼是 List 的基礎上,學習了以下重點:List 是有順序、允許重複的集合 ,可以進行索引操作 有ArrayList 和 LinkedList 兩個代表性的實作類別,特點和用途不同 掌握基本操作(新增、獲取、更新、刪除、搜尋)後,可以自由地操作數據 for 迴圈、增強型 for 迴圈、Stream API 等,根據情況進行重複處理 也能應對排序、過濾、轉換等進階處理 理解常見錯誤及其原因和處理方法,可以預防問題發生 ArrayList 與 LinkedList 的區分使用 應該使用哪種 List 實作,根據處理內容和數據量適當選擇 非常重要。以下判斷可作為參考:ArrayList :隨機存取多,以讀取為主LinkedList :經常發生插入・刪除,存取順序很重要未來學習的方向 List 僅僅是 Java 集合的「入口」。為了處理更進階的數據結構和工具,建議深入理解以下類別和功能:Set・Map :管理唯一元素、鍵值對結構Collections 工具類別 :排序、獲取最小・最大值等Stream API 的活用 :引入函數式編程泛型的理解 :型別安全的集合操作 掌握 List 的基礎,Java 程式設計整體會變得更容易掌握 。常見問題(FAQ) 整理了關於 Java List 初學者特別容易疑問的重點。嚴選了實際工作中也經常遇到的內容。Q1. Java 的 List 與陣列(Array)有什麼不同? A. 陣列的元素數量是固定的,需要在宣告時決定大小。另一方面,List 的大小是可變的,可以靈活地新增或刪除元素。此外,List 提供了許多方便的方法(add, remove, contains 等),在可讀性和維護性方面也更優越。Q2. ArrayList 與 LinkedList 應該使用哪一個? A. 主要在隨機存取(指定索引獲取) 較多的情況下適合使用 ArrayList,在經常發生元素插入・刪除 的情況下適合使用 LinkedList。如果猶豫不決,通常從 ArrayList 開始使用。Q3. List 可以存放基本型別(int 或 double 等)嗎? A. 不能直接存放。Java 的 List 只能處理物件型別,因此對於 int 等基本型別,需要使用對應的包裹類別(Integer, Double 等)。List<Integer> numbers = new ArrayList<>();
numbers.add(10); // オートボクシングされてInteger型として格納されるQ4. 想對 List 中的元素進行排序,應該怎麼做? A. 使用 Collections.sort(list) 可以按升序排序。此外,如果想按自訂順序排序,可以指定 Comparator 來自由排序。Q5. 如果想管理不重複的元素,應該怎麼做? A. List 是允許重複的集合。若要避免重複,請考慮使用 Set(例如:HashSet)。但需要注意,Set 不保證順序。如果想在 List 中排除重複,也可以使用如下的 Stream 處理:List<String> distinctList = list.stream()
.distinct()
.collect(Collectors.toList());Q6. 如果想清除 List 中的所有內容,應該怎麼做? A. 使用 clear() 方法可以刪除 List 中的所有元素。list.clear();Q7. 在 List 中最常用的操作是什麼? A. 在實際應用中最常用的是 add(新增)、get(獲取)、remove(刪除)、size(獲取大小)。掌握了這些,基本處理就可以幾乎涵蓋。