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

Java 循環語句全解析:for、while、do-while 差異、性能與最佳實踐

     編輯:Java 相關知識

三大循環語法對比

特性forwhiledo-while
語法結構for(init; condition; update) { body }while(condition) { body }do { body } while(condition);
判斷時機每次迭代前每次迭代前每次迭代後
最少執行次數001 (先執行再判斷)
變量作用域init 變量僅循環內可見外部定義,循環後可見外部定義,循環後可見
適用場景已知次數、計數器、遍歷未知次數、條件驅動菜單交互、至少一次處理

基礎語法示例

for 循環

// 經典計數
for (int i = 1; i <= 10; i++) {
    System.out.println(i);
}

// 多變量初始化/更新
for (int i = 0, j = 10; i < j; i++, j--) {
    System.out.println(i + "+" + j + "=" + (i+j));
}

// 集合遍歷 (索引)
List list = Arrays.asList("A", "B", "C");
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

// 無限循環
for (;;) { /* ... */ }

while 循環

// 條件驅動
int sum = 0, i = 1;
while (i <= 100) {
    sum += i;
    i++;
}
System.out.println(sum); // 5050

// 輸入流讀取
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
    String line;
    while ((line = br.readLine()) != null) {
        if ("exit".equals(line)) break;
        System.out.println("Echo: " + line);
    }
}

do-while 循環

// 至少執行一次:菜單選擇
Scanner sc = new Scanner(System.in);
int choice;
do {
    System.out.println("1. 查詢  2. 新增  3. 退出");
    System.out.print("請選擇: ");
    choice = sc.nextInt();
    switch (choice) {
        case 1: query(); break;
        case 2: add(); break;
        case 3: System.out.println("再見"); break;
        default: System.out.println("無效選項");
    }
} while (choice != 3);

增強 for 循環 (for-each,Java 5+)

// 集合/數組遍歷 (語法糖,編譯為 Iterator)
for (String item : list) {
    System.out.println(item);
}

int[] arr = {1, 2, 3};
for (int num : arr) {
    System.out.println(num);
}

// 限制:無索引、不可修改集合結構、不可 break/return 外層方法 (可用標籤)
outer:
for (String s : list) {
    if ("stop".equals(s)) break outer; // 跳出標籤循環
}

循環控制語句

語句作用適用循環
break立即退出最近一層循環for/while/do-while
continue跳過本次迭代剩餘代碼,進入下一次判斷for/while/do-while
return退出當前方法 (含循環)所有
標籤 label:配合 break/continue 控制外層循環巢狀循環
// 標籤示例:查找二維數組中首個負數
int[][] matrix = {{1,2}, {3,-4}, {5,6}};
boolean found = false;
search:
for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        if (matrix[i][j] < 0) {
            System.out.println("Found at [" + i + "][" + j + "]");
            found = true;
            break search; // 直接跳出雙層
        }
    }
}

性能與字節碼視角

  • for/while/do-while 編譯後字節碼幾乎等價,JIT 編譯器會優化為相同機器碼
  • for-each 編譯為 Iterator 模式,非 RandomAccess 集合 (LinkedList) 效率等同手寫 Iterator
  • 循環不變量外提:JIT 自動將循環內不變的計算/方法調用外提
  • 逃逸分析/標量替換:循環內新建對象若未逃逸,可能優化為棧分配或消除

微優化技巧 (極少數熱點循環才需關注)

// 1. 緩存長度 (ArrayList 獲取 size() 極快,但習慣寫法)
int len = list.size();
for (int i = 0; i < len; i++) { ... }

// 2. 反向循環避免邊界檢查 (JIT 通常自動優化)
for (int i = len - 1; i >= 0; i--) { ... }

// 3. 局部變量引用字段 (避免重複字段讀取)
Object localRef = this.field;
for (int i = 0; i < len; i++) { localRef.method(); }

// 4. 基本類型優於包裝類型 (避免拆箱裝箱)
int sum = 0; // 而非 Integer sum = 0;
for (int i = 0; i < 1000000; i++) sum += i;

函數式替代方案 (Java 8+)

命令式循環Stream API 替代優勢
遍歷打印list.forEach(System.out::println)聲明式、可鏈式
過濾收集list.stream().filter(x>0).collect(toList())管道組合、並行化
求和/統計list.stream().mapToInt(Integer::intValue).sum()專用減少操作
查找首個list.stream().filter(...).findFirst()短路優化
分組統計list.stream().collect(groupingBy(...))聲明式聚合

常見錯誤與避坑

錯誤代碼問題修正
for(int i=0; i<=list.size(); i++)索引越界 (size() 而非 size()-1)i < list.size()
循環中修改集合結構ConcurrentModificationException用 Iterator.remove() / removeIf() / 反向索引
while(true) { ... } 無 break死循環導致 CPU 100%確保有退出條件或中斷機制
浮點數作為循環條件精度誤差導致多執行/少執行用整數計數器或 BigDecimal
do { } while(false);偽裝的一次性代碼塊,可讀性差直接用代碼塊 { } 或提取方法

最佳實踐決策指南

已知確切迭代次數/需要計數器?
  ├─ 是 → for (int i=0; i

總結

Java 提供 for、while、do-while 三大基礎循環 + for-each 語法糖 + Stream API 函數式替代。核心差異在於判斷時機 (前/後)與最少執行次數 (0/1)。性能上 JIT 使基礎循環等效,熱點循環可微優化。選擇原則:已知次數用 for、至少一次用 do-while、條件驅動用 while、複雜管道用 Stream、巢狀跳出用標籤。避開修改集合、浮點判斷、死循環等常見陷阱。

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