在 Java 開發中,集合遍歷是最基礎也最常用的操作之一。無論是處理業務邏輯、資料轉換還是效能調優,選擇正確的遍歷方式都能事半功倍。本文將系統整理 List 與 Map 的主流遍歷寫法,並從語法、適用場景、效能等維度進行對比,幫助你在實際專案中做出最佳選擇。
以 ArrayList<String> 為例,裝載 5 筆測試資料:
@Test
public void iteratorTraverse() {
List<String> list = new ArrayList<>();
list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5");
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String val = it.next();
System.out.println("Iterator: " + val);
}
}
it.remove())。@Test
public void forEachTraverse() {
List<String> list = new ArrayList<>();
list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5");
for (String val : list) {
System.out.println("for-each: " + val);
}
}
ConcurrentModificationException)。@Test
public void classicForTraverse() {
List<String> list = new ArrayList<>();
list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5");
for (int i = 0; i < list.size(); i++) {
System.out.println("classic for: " + list.get(i));
}
}
ArrayList 等隨機存取結構效能最優。LinkedList 效能極差(get(i) 為 O(n)),需自行管理邊界條件。以 HashMap<String, String> 為例:
for (String key : map.keySet()) {
String val = map.get(key);
System.out.println("keySet: key=" + key + ", value=" + val);
}
get(key),涉及兩次雜湊查找,效能較差。for (Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
System.out.println("entrySet-Iterator: " + entry.getKey() + "=" + entry.getValue());
}
remove() 的場景。for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("entrySet-forEach: " + entry.getKey() + "=" + entry.getValue());
}
for (String val : map.values()) {
System.out.println("values-only: " + val);
}
| 集合類型 | 推薦方式 | 適用場景 | 避坑提醒 |
|---|---|---|---|
| ArrayList | for-each / 傳統 for | 順序讀取、需索引運算 | 遍歷中勿修改結構 |
| LinkedList | for-each / Iterator | 順序讀取、頻繁增刪 | 嚴禁傳統 for + get(i) |
| HashMap / LinkedHashMap | entrySet + for-each | 同時需 key/value | keySet+get 效能較差 |
| TreeMap | entrySet + for-each | 需有序遍歷 | 同 HashMap |
若專案已升級至 Java 8,可善用 Stream API 與 forEach:
// List
list.forEach(System.out::println);
// Map
map.forEach((k, v) -> System.out.println(k + "=" + v));
// 或平行流處理大量資料
map.entrySet().parallelStream().forEach(entry -> { /* 處理邏輯 */ });
Stream 提供鏈式操作(filter、map、collect 等),適合複雜資料管線;但簡單遍歷仍以 for-each 為主,避免過度設計。
遍歷看似微不足道,卻貫穿整個系統的讀寫路徑。掌握各集合的最佳遍歷姿勢,不僅能寫出更乾淨的程式碼,更能在高併發、大資料量場景下避免效能陷阱。建議將「List 用 for-each,Map 用 entrySet」作為肌肉記憶,特殊場景再視需求調整。