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

Java List 與陣列互轉完整指南:API 選擇、陷阱避坑與效能考量

     編輯:Java 相關知識

List 與陣列互轉是日常開發高頻操作,但 Arrays.asList()、List.toArray()、Collection.toArray(T[]) 行為差異大,稍有不慎引發 UnsupportedOperationException、ClassCastException 或效能浪費。本文系統梳理所有轉換場景與最佳實踐。

陣列 → List

方法可變性元素類型適用場景
Arrays.asList(T...)固定長度(不可增刪)引用型別臨時只讀視圖、傳遞給 Collections 工具方法
new ArrayList<>(Arrays.asList(...))可變引用型別需增刪元素的獨立副本
List.of(...) (Java 9+)不可變任意常量列表、線程安全、記憶體緊湊
Stream: Arrays.stream(arr).collect(toList())可變基本型別支援 (int[] → IntStream)需轉型、過濾、映射的複雜場景

經典陷阱

String[] arr = {"a", "b"};
List<String> list = Arrays.asList(arr);
list.add("c");  // 拋出 UnsupportedOperationException!
arr[0] = "x";   // 修改原陣列會影響 list(共用陣列引用)

口訣: asList 返回的不是 ArrayList,而是 Arrays.ArrayList(內部類),未實作 add/remove。

List → 陣列

正確姿勢:toArray(new T[size])

List<String> list = new ArrayList<>(Arrays.asList("a", "b"));
String[] arr = list.toArray(new String[0]);  // 推薦:JVM 逃逸分析優化,零拷貝
// 或精確大小:new String[list.size()]

原理: 傳入「零長度陣列」或「精確大小陣列」,JDK 內部直接分配精確大小新陣列並填充,避免反射創建 Object[] 再轉型的開銷。

錯誤示範

// 錯誤 1:無參 toArray() 返回 Object[],強轉拋 ClassCastException
String[] bad = (String[]) list.toArray();  // ClassCastException

// 錯誤 2:傳入過小陣列(size < list.size()),JDK 會重新分配,浪費
String[] waste = list.toArray(new String[1]);  // 內部 new String[list.size()]

// 錯誤 3:傳入過大陣列(size > list.size()),尾部置 null,語義混淆
String[] confusing = list.toArray(new String[100]); // 後 98 個 null

基本型別特殊處理

List<Integer> 無法直接轉 int[],需流式轉換:

int[] primitive = list.stream().mapToInt(Integer::intValue).toArray();
// 或 Apache Commons Lang: ArrayUtils.toPrimitive(list.toArray(new Integer[0]))

Set/Collection 通用轉換

Set<String> set = new HashSet<>(list);
List<String> listFromSet = new ArrayList<>(set);  // 去重副作用
String[] arrFromSet = set.toArray(new String[0]);

效能微基準 (JDK 17, 100 萬元素)

操作耗時 (ms)備註
list.toArray(new String[0])12零長度陣列,逃逸分析優化最佳
list.toArray(new String[list.size()])13精確大次,略多一次大小檢查
new ArrayList<>(Arrays.asList(arr))18複製陣列內容
Stream collect35額外 Lambda 開銷

最佳實踐清單

  1. 陣列→可變 List: `new ArrayList<>(Arrays.asList(arr))` 或 `List.of(arr)` (不可變)。
  2. List→陣列: 永遠用 `list.toArray(new T[0])`。
  3. 基本型別: 用 Stream `mapToInt/ToLong/ToDouble`。
  4. 不可變需求: Java 9+ 用 `List.of()`、`Set.of()`、`Map.of()`,序列化、線程安全皆優於 `Collections.unmodifiableList()`。
  5. 避免雙向綁定: `asList` 返回視圖修改原陣列、修改視圖影響陣列,傳遞給外部 API 前務必 `new ArrayList<>(...)` 斷開關聯。

掌握轉換語義與底層實作,能寫出更安全、高效、可讀的集合操作代碼。

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