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

Java List 遍歷方式全解析:性能、場景與最佳實踐

     編輯:Java 相關知識

五大主流遍歷方式

List list = Arrays.asList("Java", "Python", "Go", "Rust");

1. 經典 for 循環(索引訪問)

for (int i = 0; i < list.size(); i++) {
    String item = list.get(i);
    System.out.println(item);
}
  • 優點:可控索引、支持逆序、可修改列表結構(謹慎)、隨機訪問集合 O(1)
  • 缺點:樣板代碼多、鏈表 get(i) 為 O(n) 導致整體 O(n²)
  • 適用:ArrayList、需要索引、需在遍歷中增刪元素

2. 增強 for 循環(for-each,語法糖)

for (String item : list) {
    System.out.println(item);
}
  • 本質:編譯器轉為 Iterator 模式
  • 優點:代碼簡潔、語義清晰、防止索引越界
  • 缺點:無索引、不可移除元素(拋 ConcurrentModificationException)、不可替換元素
  • 適用:純讀取遍歷、不需索引

3. Iterator 顯式迭代器

Iterator it = list.iterator();
while (it.hasNext()) {
    String item = it.next();
    System.out.println(item);
    // 安全移除
    if ("Go".equals(item)) it.remove();
}
  • 優點:唯一安全在遍歷中修改結構(remove())、支持泛型
  • 缺點:代碼較繁瑣、單向遍歷
  • 適用:遍歷中需刪除元素、舊版本兼容

4. ListIterator 雙向迭代器(List 專有)

ListIterator lit = list.listIterator();
while (lit.hasNext()) {
    int index = lit.nextIndex();
    String item = lit.next();
    System.out.println(index + ": " + item);
}
// 逆向遍歷
while (lit.hasPrevious()) {
    System.out.println(lit.previous());
}
  • 特有功能:雙向遍歷、獲取索引 nextIndex()/previousIndex()、add()/set() 修改
  • 適用:雙向遍歷、需索引、遍歷中增改元素

5. Java 8+ Stream 流式遍歷

// 內部迭代,聲明式
list.forEach(System.out::println);           // 簡單消費
list.stream().filter(s -> s.startsWith("J")).forEach(System.out::println); // 過濾
list.parallelStream().forEach(System.out::println); // 並行(無序)
  • 優點:函數式風格、鏈式操作(filter/map/sort/collect)、易並行化
  • 缺點:簡單遍歷有開銷、調試困難、無法直接 break/return 外層方法
  • 適用:複雜數據處理管道、並行計算、函數式編程風格

性能對比實測(百萬級數據)

方式ArrayList (ms)LinkedList (ms)備註
for 索引~15~45000LinkedList get(i) 為 O(n)
for-each~18~22均委託 Iterator
Iterator~18~22基準性能
ListIterator~20~24略高開銷
forEach (Lambda)~22~26Lambda 開銷
Stream 串行~30~35管道開銷
parallelStream~12 (8核)~40000LinkedList 不支持高效分割

結論:ArrayList 首選索引 for 或 for-each;LinkedList 必須用迭代器/for-each;並行流僅適合隨機訪問集合。

避坑指南

錯誤場景後果正確做法
for-each 中 list.remove()ConcurrentModificationException用 Iterator.remove() 或反向索引 for
for 索引正向刪除跳過元素/索引越界反向 for (i = size-1; i>=0; i--)
並發修改未同步數據不一致/CME用 CopyOnWriteArrayList 或加鎖/並發集合
Stream 中 break無法跳出用 takeWhile() (JDK 9+) 或傳統循環
Lambda 捕獲非 final 變量編譯錯誤變量實際最終不可變,或用數組/AtomicReference 包裝

最佳實踐決策樹

需要索引嗎?
  ├─ 是 → ArrayList: 索引 for / LinkedList: ListIterator
  └─ 否
       遍歷中需刪除/修改結構?
         ├─ 是 → Iterator.remove() / ListIterator.add()/set()
         └─ 否
              純讀取、簡單邏輯?
                ├─ 是 → for-each (最推薦)
                └─ 否 (複雜過濾/轉換/聚合)
                     └─ Stream API (filter/map/collect)
                     並行計算、CPU 密集?
                       └─ parallelStream (確認隨機訪問集合)

總結

Java List 遍歷無絕對最優,核心原則:ArrayList 用索引 for/for-each,LinkedList 用迭代器/for-each,遍歷中改結構用 Iterator/ListIterator,複雜邏輯用 Stream,並行流僅用於隨機訪問集合。理解底層機制(隨機訪問 vs 循序訪問、外部 vs 內部迭代、快速失效),根據場景選擇最適方式。

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