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

Java 集合框架核心實戰:List、Set、Map 典型應用場景與性能抉擇

     編輯:Java 相關知識

一個統計字符頻次的引子

假設需求:從控制台讀取一行字符串,統計每個字符出現的次數。這是一個經典的「去重 + 計數」場景,恰好能串起 List、Set、Map 三大集合的核心特性。

public class CharFrequencyCounter {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("請輸入字符串: ");
        String input = scanner.nextLine();
        scanner.close();

        // 1. List 保持順序、允許重複 —— 存儲所有字符(含重複)
        List<Character> charList = new ArrayList<>();
        for (char c : input.toCharArray()) {
            charList.add(c);
        }

        // 2. Set 自動去重、無序 —— 獲取唯一字符集合
        Set<Character> uniqueChars = new LinkedHashSet<>(charList); // 保持首次出現順序

        // 3. Map 鍵值映射 —— 字符 -> 出現次數
        Map<Character, Integer> frequencyMap = new LinkedHashMap<>();
        for (Character c : uniqueChars) {
            int count = Collections.frequency(charList, c); // O(n) 但代碼簡潔
            frequencyMap.put(c, count);
        }

        // 輸出結果
        frequencyMap.forEach((k, v) -> System.out.println(k + " 出現 " + v + " 次"));
    }
}

三大集合核心特性對比

特性ListSetMap
是否允許重複是否Key 不重複,Value 可重複
是否有序按插入序有序HashSet 無序
LinkedHashSet 插入序
TreeSet 自然序/定制序
HashMap 無序
LinkedHashMap 插入序/訪問序
TreeMap 自然序/定制序
核心實現類ArrayList、LinkedList、VectorHashSet、LinkedHashSet、TreeSetHashMap、LinkedHashMap、TreeMap、Hashtable
線程安全Vector、Collections.synchronizedListCollections.synchronizedSetHashtable、Collections.synchronizedMap、ConcurrentHashMap
典型場景有序數據、按索引訪問、允許重複去重、集合運算(交/並/差)、唯一性約束鍵值查找、緩存、分組統計、對象映射

深度解析:ArrayList vs LinkedList

  • ArrayList:動態數組,隨機訪問 O(1),尾部插入摊還 O(1),中間增刪 O(n) 需搬移元素。首選場景:頻繁讀、少量寫、末尾追加。
  • LinkedList:雙向鏈表,隨機訪問 O(n),首尾增刪 O(1),中間增刪僅需修改指針。適用場景:頻繁頭尾操作、作為隊列/棧。
  • Vector:同步化的 ArrayList,性能較差,已被 Collections.synchronizedList 或 CopyOnWriteArrayList 替代。

HashMap 核心機制與 JDK 8 優化

  1. 哈希桶 + 鏈表/紅黑樹:Key 的 hashCode() & (n-1) 定位桶位置。
  2. 擴容機制:負載因子默認 0.75,容量翻倍,JDK 8 採用「高位運行」優化避免重新計算 hash。
  3. 鏈表轉紅黑樹:桶內節點 ≥ 8 且容量 ≥ 64 時轉為紅黑樹,查詢從 O(n) 降為 O(log n),防禦 HashDoS 攻擊。
  4. null 支持:允許一個 null key、多個 null value;Hashtable 全不允許。

選型決策樹(實戰速查)

需要鍵值映射? ──Yes──► Map
  ├─ 需保持插入序? ──Yes──► LinkedHashMap
  ├─ 需按 Key 排序? ──Yes──► TreeMap
  ├─ 高併發寫入? ──Yes──► ConcurrentHashMap
  └─ 一般場景 ──► HashMap

不需要鍵值映射?
  ├─ 需去重?
  │   ├─ 需保持插入序? ──Yes──► LinkedHashSet
  │   ├─ 需排序? ──Yes──► TreeSet
  │   └─ 一般場景 ──► HashSet
  └─ 允許重複、需有序?
      ├─ 頻繁隨機訪問/末尾追加? ──Yes──► ArrayList
      ├─ 頻繁頭尾增刪/作為隊列? ──Yes──► LinkedList
      └─ 多線程只讀/寫少? ──► CopyOnWriteArrayList

常見陷阱與避坑指南

  1. 遍歷時修改:使用 Iterator.remove() 或 ListIterator,或先收集待刪元素再批量移除。
  2. 自定義對象作 Key/元素:必須重寫 equals() 和 hashCode(),且保持一致性(相等對象 hashCode 必相等)。
  3. 初始容量預估:大數據量場景 new ArrayList<>(estimatedSize)、new HashMap<>((int)(size/0.75)+1) 避免頻繁擴容。
  4. 並發環境:非線程安全集合加鎖或改用並發版本(ConcurrentHashMap、CopyOnWriteArrayList),切勿用 Vector/Hashtable。

總結

List、Set、Map 構成了 Java 集合框架的基石。理解其底層數據結構(數組、鏈表、哈希表、紅黑樹)、線程安全模型、以及各實現類的性能邊界,是寫出高效、穩健代碼的前提。下次選型時,請先問自己三個問題:需不需要鍵值?允不允許重複?有沒有順序/排序/併發要求? 答案即指引。

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