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

Java 集合框架深度解析:List 接口與核心實現類全攻略

     編輯:Java 綜合教學

Java 集合框架深度解析:List 接口與核心實現類全攻略

在上一篇文章中,我們詳細介紹了 Collection 接口作為集合體系的根接口。本文將深入探討其核心子接口 List,解析其特有方法、核心實現類(ArrayList、LinkedList、Vector)的底層原理與最佳實踐,幫助你在實際開發中靈活選型、高效編碼。

一、List 接口核心特性

List 接口繼承自 Collection,具有三大核心特徵:

  • 有序性:元素存入與取出順序一致,擁有索引(下標)概念。
  • 可重複性:允許存放重複元素,equals() 比較為 true 即視為重複。
  • 索引訪問:提供基於索引的增、刪、改、查操作,這是區別於 Set 的關鍵。

二、List 特有核心方法詳解

所有方法均圍繞「索引」展開,以下為高頻 API 分類速查:

1. 新增元素

// 在指定索引處插入單個元素,原索引及之後元素後移
void add(int index, E element);

// 批量插入集合,從指定索引開始
boolean addAll(int index, Collection<? extends E> c);

2. 刪除元素

// 移除指定索引處元素,返回被移除的元素
E remove(int index);

3. 修改元素

// 替換指定索引處元素,返回舊元素
E set(int index, E element);

4. 查詢與定位

// 獲取指定索引元素
E get(int index);

// 正向查找首次出現索引,無則返回 -1
int indexOf(Object o);

// 反向查找最後出現索引
int lastIndexOf(Object o);

// 截取子列表 [fromIndex, toIndex) 左閉右開
List<E> subList(int fromIndex, int toIndex);

三、核心實現類深度對比

1. ArrayList — 動態數組,查詢王者

  • 底層結構:可擴容的 Object[] 數組(JDK 1.7+ 懶加載,首次 add 時初始化容量 10)。
  • 擴容機制:1.5 倍擴容(newCapacity = oldCapacity + (oldCapacity >> 1)),涉及 Arrays.copyOf 數組拷貝,頻繁擴容影響性能,建議預估數據量用 new ArrayList<>(initialCapacity)。
  • 優勢:隨機訪問 get(i)、遍歷極快(O(1)),CPU 緩存友好。
  • 劣勢:頭部/中間插入刪除需移動數組元素(O(n)),頻繁修改場景不適用。
  • 線程安全:非線程安全,多線程環境下請用 Collections.synchronizedList 或 CopyOnWriteArrayList。

2. LinkedList — 雙向鏈表,修改高手

  • 底層結構:雙向鏈表(JDK 1.7+ 移除 header 節點,改用 first/last 指針),節點內含 prev、next、item。
  • 優勢:頭尾增刪 O(1),中間增刪僅需修改指針(定位仍需 O(n)),適合頻繁增刪、作為隊列/棧(實現 Deque 接口)。
  • 劣勢:隨機訪問 get(i) 需遍歷(O(n)),記憶體佔用大(每個節點額外存兩個引用),不利於 CPU 緩存。
  • 線程安全:同樣非線程安全。

3. Vector — 歷史遺留,同步數組

  • 底層:同步版 ArrayList,所有方法加 synchronized。
  • 擴容:預設 2 倍擴容,可通過 capacityIncrement 調整。
  • 現狀:性能差、API 臃腫,實際開發極少直接使用,僅作為歷史兼容存在。

四、選型決策指南

場景 推薦實現類 理由
頻繁隨機訪問、遍歷、尾部增刪 ArrayList 數組連續內存,緩存命中率高,get/set O(1)
頻繁頭部/中間增刪、作為隊列/棧 LinkedList 指針操作無需移動數據,實現 Deque 接口
多線程高併發讀寫 CopyOnWriteArrayList 寫時復制,讀無鎖,適合「讀多寫少」場景
多線程均衡讀寫 Collections.synchronizedList(new ArrayList<>()) 全量同步,簡單但吞吐一般

五、實戰代碼範例:課程管理系統

以下示例展示 List 常用操作,包含自定義對象存儲、索引操作、子列表截取等:

// 實體類
public class Course {
    private String id;
    private String name;
    // 構造器、getter/setter、toString 省略
}

// 測試類
public class ListDemo {
    public static void main(String[] args) {
        List<Course> courses = new ArrayList<>();

        // 1. 尾部新增
        courses.add(new Course("1", "數據庫原理"));
        courses.add(new Course("2", "Java 核心技術"));

        // 2. 指定索引插入(頭部插入)
        courses.add(0, new Course("0", "計算機導論")); // 現索引 0

        // 3. 批量新增
        Course[] newCourses = {
            new Course("3", "高等數學"),
            new Course("4", "大學英語")
        };
        courses.addAll(Arrays.asList(newCourses));

        // 4. 指定位置批量插入
        Course[] moreCourses = {
            new Course("5", "高等語文"),
            new Course("6", "數據處理")
        };
        courses.addAll(2, Arrays.asList(moreCourses)); // 插入到索引 2

        // 5. 遍歷輸出
        System.out.println("=== 所有課程 ===");
        for (int i = 0; i < courses.size(); i++) {
            System.out.printf("[%d] %s%n", i, courses.get(i));
        }

        // 6. 修改與刪除
        Course old = courses.set(1, new Course("1", "數據庫系統工程師")); // 修改
        System.out.println("修改前:" + old);
        Course removed = courses.remove(3); // 刪除索引 3
        System.out.println("刪除:" + removed);

        // 7. 查找索引
        int idx = courses.indexOf(new Course("2", "Java 核心技術")); // 需重寫 equals
        System.out.println("Java 課程索引:" + idx);

        // 8. 截取子列表(索引 1 到 4,不含 4)
        List<Course> sub = courses.subList(1, 4);
        System.out.println("子列表:" + sub);
    }
}

六、避坑指南與最佳實踐

  1. 預估容量:大量數據時用 new ArrayList<>(n) 避免多次擴容拷貝。
  2. 避免在循環中 remove:正向遍歷刪除會導致索引錯位,請使用 Iterator.remove()、逆向遍歷或 Stream 流過濾。
  3. subList 視圖特性:返回視圖,對子列表修改會影響原列表,且原列表結構性修改會導致子列表失效(拋 ConcurrentModificationException)。
  4. 泛型擦除注意:List<Course> list = new ArrayList<>(); 編譯期泛型,運行期擦除,取出時無需強轉。
  5. 不可變列表:JDK 9+ 用 List.of()、Collections.unmodifiableList() 構建只讀列表,防止誤修改。

七、總結

List 接口賦予集合「有序、可重複、可索引」三大特性,ArrayList 與 LinkedList 分別代表「數組」與「鏈表」兩大經典數據結構在 Java 中的工程化實現。掌握其底層原理、擴容機制、時間複雜度差異,結合業務場景(查詢多選 ArrayList、增刪多選 LinkedList、併發選 CopyOnWriteArrayList),才能寫出高性能、穩健的 Java 代碼。下一篇我們將深入 Set 接口及其 HashSet、LinkedHashSet、TreeSet 實現,敬請期待!

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