首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 集合框架深度解析:List 介面完整指南與實戰範例

     編輯:Java 相關知識

前言

List 是 Collection 子介面,代表有序、可重複、允許 null 的元素序列。本文系統整理 List 核心方法、三大實作類別差異、迭代器用法、並發修改異常處理與效能選型建議,附完整可執行範例程式碼。

List 核心特性

  • 有序:插入順序 = 迭代順序
  • 可重複:允許相同元素多次出現
  • 允許 null:可存放任意數量 null
  • 支援索引:get(index)、set(index, e)、add(index, e)

三大主流實作比較

實作類別底層結構查詢增刪(頭/中間)增刪(尾部)線程安全適用場景
ArrayList動態陣列O(1)O(N)O(1) 攤還否隨機存取多、尾部增刪
LinkedList雙向鏈表O(N)O(1)O(1)否頻繁頭/中間增刪、佇列/棧
Vector動態陣列O(1)O(N)O(1)是 (synchronized)舊代碼相容、極少用

核心方法分類詳解

1. 新增元素


List list = new ArrayList<>();
list.add("紅樓夢");                    // 尾部新增
list.add(1, "偉大的世界");             // 指定索引插入,後續元素右移
list.addAll(Arrays.asList("西遊記", "水滸傳")); // 尾部批量新增
list.addAll(1, otherList);             // 指定索引批量插入

// 索引越界拋 IndexOutOfBoundsException
// list.add(5, "錯誤"); // Size=4 時拋出異常

2. 取得元素


String first = list.get(0);                    // 索引取得
int idx = list.indexOf("紅樓夢");              // 首次出現索引 (0)
int lastIdx = list.lastIndexOf("紅樓夢");      // 最後出現索引 (4)
List sub = list.subList(1, 3);         // 視圖 [1,3),不含索引 3
// sub 為視圖,修改 sub 會影響原 list,反之亦然

3. 刪除元素


String removed = list.remove(1);               // 刪除索引 1,回傳被刪元素
// 後續元素左移,索引自動更新
boolean removed2 = list.remove("水滸傳");      // 刪除首個匹配元素,回傳是否成功
list.clear();                                  // 清空

4. 修改元素


list.set(0, "偉大的世界");                     // 替換索引 0 元素

5. 遍歷方式效能比較

方式程式碼ArrayListLinkedList備註
for 迴圈 + getfor(i=0;i★★★★★★☆☆☆☆ArrayList 隨機存取快
for-eachfor(String s : list)★★★★★★★★★★語法糖,內部用 Iterator
Iteratorwhile(it.hasNext()) it.next()★★★★★★★★★★通用、可安全移除
ListIterator雙向遍歷、可增刪改★★★★★★★★★★List 專用,功能最強
forEach (Java 8)list.forEach(s -> ...)★★★★★★★★★★內部迭代,可能較快

6. ListIterator 進階用法


ListIterator it = list.listIterator();

// 正向遍歷
while (it.hasNext()) {
    System.out.println(it.next());
}

// 反向遍歷 (需先正向走到底)
while (it.hasPrevious()) {
    System.out.println(it.previous());
}

// 迭代器操作元素 (安全)
while (it.hasNext()) {
    String s = it.next();
    if ("三國演義".equals(s)) {
        it.add("西遊記");      // 在當前位置前插入
        it.set("新三國演義");  // 替換剛讀取的元素
    }
}
// it.remove() 刪除上次 next()/previous() 返回的元素

並發修改異常 完整解決方案

問題重現


List list = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String s : list) { // 隱式使用 Iterator
    if ("B".equals(s)) {
        list.add("D"); // ConcurrentModificationException!
    }
}

三種解決方案

  1. Iterator 迭代 + Iterator 修改 (推薦)

Iterator it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if ("B".equals(s)) {
        it.remove(); // 或 it.add("D") - 需 ListIterator
    }
}
  1. 普通 for 迴圈 + 索引修改 (僅限 ArrayList/RandomAccess)

for (int i = 0; i < list.size(); i++) {
    if ("B".equals(list.get(i))) {
        list.add(i + 1, "D"); // 索引控制精確
        i++; // 跳過新增元素
    }
}
  1. 收集待處理索引/元素,迴圈外批量操作

List toRemove = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
    if ("B".equals(list.get(i))) toRemove.add(i);
}
for (int i = toRemove.size() - 1; i >= 0; i--) {
    list.remove(toRemove.get(i).intValue()); // 從後往前刪,索引不變
}

實戰範例:完整 CRUD 操作示範


public class ListDemo {
    public static void main(String[] args) {
        List books = new ArrayList<>();
        
        // Create
        books.add("紅樓夢");
        books.add("三國演義");
        books.add("三國演義"); // 可重複
        books.add(null);       // 允許 null
        System.out.println("初始:" + books);
        
        // Read
        System.out.println("索引 0:" + books.get(0));
        System.out.println("首現 '三國演義':" + books.indexOf("三國演義"));
        System.out.println("末現 '三國演義':" + books.lastIndexOf("三國演義"));
        System.out.println("子列表 [1,3):" + books.subList(1, 3));
        
        // Update
        books.set(0, "偉大的世界");
        System.out.println("修改後:" + books);
        
        // Delete
        String removed = books.remove(1);
        System.out.println("刪除索引 1:" + removed + ",剩餘:" + books);
        
        // 遍歷
        System.out.println("--- for-each ---");
        for (String b : books) System.out.println(b);
        
        System.out.println("--- ListIterator 反向 ---");
        ListIterator it = books.listIterator(books.size());
        while (it.hasPrevious()) System.out.println(it.previous());
    }
}

輸出結果

初始:[紅樓夢, 三國演義, 三國演義, null]
索引 0:紅樓夢
首現 '三國演義':1
末現 '三國演義':2
子列表 [1,3):[三國演義, 三國演義]
修改後:[偉大的世界, 三國演義, 三國演義, null]
刪除索引 1:三國演義,剩餘:[偉大的世界, 三國演義, null]
--- for-each ---
偉大的世界
三國演義
null
--- ListIterator 反向 ---
null
三國演義
偉大的世界

選型建議總結

  1. 預設用 ArrayList:90% 場景足夠,隨機存取快、記憶體緊湊
  2. 頻繁頭部/中間增刪:LinkedList (實作 Queue/Deque 介面)
  3. 多線程環境:Collections.synchronizedList() 或 CopyOnWriteArrayList (讀多寫少)
  4. 固定大小、只讀:List.of() (Java 9+) 不可變列表
  5. 基本型別列表:避免裝箱開銷,用第三方庫 (Eclipse Collections, FastUtil) 或陣列

總結

List 是 Java 集合框架使用率最高的介面。掌握 ArrayList vs LinkedList 底層差異、索引操作語意、迭代器安全模式、並發修改異常三大解法,能解決 99% 實際開發中的列表操作問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved