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

高品質 Java 程式碼建議 65-69:陣列轉 List 陷阱、遍歷優化與集合相等性

     編輯:Java 綜合教學

高品質 Java 程式碼建議 65-69:陣列轉 List 陷阱、遍歷優化與集合相等性

本文整理自《編寫高質量代碼:改善 Java 程序的 151 個建議》第 5 章,深入剖析陣列與集合使用中的常見陷阱與最佳實踐,包含原始型別陣列轉換、asList 不可變性、List 遍歷效能、LinkedList 與 ArrayList 選型、集合相等性判斷等核心議題。

建議 65:避開基本型別陣列轉 List 陷阱

int[] data = {1, 2, 3, 4, 5};
List list = Arrays.asList(data); // 陷阱!
System.out.println(list.size()); // 輸出 1,非 5

原因:Arrays.asList(T... a) 接收泛型可變參數,基本型別無法泛型化。int[] 被視為單一元素(型別為 int[]),而非 5 個 Integer。

解決:使用包裝類型 Integer[] 替代 int[]。

注意:8 種基本型別陣列均存在此問題,轉 List 時必須使用包裝類型陣列。

建議 66:asList 回傳的 List 不可修改長度

List<String> names = Arrays.asList("張三", "李四", "王五");
names.add("趙六"); // 拋出 UnsupportedOperationException

原因:Arrays.asList 回傳的是 Arrays 內部類 ArrayList(非 java.util.ArrayList),未覆寫 add/remove 方法,父類 AbstractList 預設拋出異常。

對策:

  • 僅需唯讀操作時使用 asList
  • 需修改長度時:new ArrayList<>(Arrays.asList(...))

建議 67:不同 List 選擇不同遍歷演算法

核心原則:實作 RandomAccess 介面(如 ArrayList)用索引遍歷;未實作(如 LinkedList)用迭代器/foreach 遍歷。

public static int average(List<Integer> scores) {
    int sum = 0;
    if (scores instanceof RandomAccess) {
        // 隨機存取:索引遍歷更快
        for (int i = 0; i < scores.size(); i++) {
            sum += scores.get(i);
        }
    } else {
        // 循序存取:迭代器遍歷更快
        for (Integer score : scores) {
            sum += score;
        }
    }
    return sum / scores.size();
}

效能實測(80 萬筆資料):

  • ArrayList:索引遍歷 8ms vs foreach 11ms
  • LinkedList:foreach 12ms vs 索引遍歷極慢(每次 get 需從頭/尾遍歷)

建議 68:頻繁插入刪除用 LinkedList,頻繁修改用 ArrayList

操作ArrayListLinkedList勝出
插入需陣列拷貝位移 O(n)僅修改指標 O(1)LinkedList
刪除需陣列拷貝位移 O(n)僅修改指標 O(1)LinkedList
修改直接索引賦值 O(1)需遍歷定位 O(n)ArrayList
隨機存取O(1)O(n)ArrayList

實務建議:寫多讀少、頻繁頭尾操作選 LinkedList;讀多寫少、需隨機存取選 ArrayList(預設首選)。

建議 69:集合相等性僅關注元素資料

ArrayList<String> list1 = new ArrayList<>();
list1.add("A");
Vector<String> list2 = new Vector<>();
list2.add("A");
System.out.println(list1.equals(list2)); // true

原理:AbstractList.equals() 僅檢查:

  1. 是否同為 List 介面實作
  2. 長度是否相等
  3. 對應位置元素是否 equals 相等

完全不關心具體實作類別(ArrayList、Vector、LinkedList 等)。Set、Map 同理。

總結

這五個建議揭示了 Java 集合框架設計的核心哲學:介面抽象、效能權衡、防禦性程式設計。深入理解底層實作(陣列 vs 鏈表、隨機存取 vs 循序存取、淺拷貝 vs 深拷貝),才能在實戰中做出正確選擇,避開隱藏陷阱,寫出高效、健壯的程式碼。

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