Java 循环结构

Java 循环结构

循环结构概述

循环结构用于重复执行一段代码,直到满足特定条件为止。Java 提供三种核心循环结构:while 循环、for 循环和 do-while 循环,它们的核心组成部分一致,仅执行顺序和语法格式不同,具体包含四部分:

  1. 初始化部分:仅执行一次,用于初始化循环变量(如计数器、随机数等)。
  2. 循环条件部分:布尔表达式,结果为 true 时执行循环体,为 false 时终止循环。
  3. 循环体部分:需要重复执行的核心代码块。
  4. 迭代部分:循环体执行后更新循环变量(如计数器自增、读取新输入等),避免无限循环。

while 循环

while 循环是“先判断,后执行”的结构,循环体可能一次都不执行(若初始条件为 false)。

语法格式

// ① 初始化部分(仅执行一次)
while (② 循环条件部分) { 
    ③ 循环体部分(条件为true时执行)
    ④ 迭代部分(更新循环变量)
}

执行顺序:① → ②(判断)→ ③(条件满足时)→ ④ → ② → ... → ②(条件不满足,循环终止)

典型案例

案例1:加法练习(直到答案正确为止)

需求:随机生成两个个位数,让用户输入答案,重复提示直到输入正确。

package com.loop;

import java.util.Scanner;

/**
 * @Author Jing61
 * 功能:加法练习,重复输入直到答案正确
 */
public class AdditionQuiz {
    public static void main(String[] args) {
        // ① 初始化:生成两个0-9的随机整数
        int number1 = (int)(Math.random() * 10);
        int number2 = (int)(Math.random() * 10);
        
        // 提示用户输入
        System.out.printf("%d + %d = ?,请输入答案 \n", number1, number2);
        Scanner input = new Scanner(System.in);
        int answer = input.nextInt(); // 读取初始答案
        
        // ② 循环条件:答案不正确则继续循环
        while (answer != number1 + number2) {
            // ③ 循环体:提示错误并重新请求输入
            System.out.println("答案错误,重新输入," + number1 + " + " + number2 + " = ?");
            // ④ 迭代:读取新答案(更新循环变量)
            answer = input.nextInt();
        }
        
        // 循环终止:输出正确提示
        System.out.printf("%d + %d = %d 的答案是正确的", number1, number2, answer);
        input.close(); // 关闭输入流
    }
}

案例2:猜数字游戏(0-99)

需求:程序随机生成 0-99 的数字,用户猜测,提示“太大”或“太小”,直到猜对。

package com.loop;

import java.util.Scanner;

/**
 * @Author Jing61
 * 功能:猜数字游戏(0-99),根据提示缩小范围
 */
public class GuessNumber {
    public static void main(String[] args) {
        // ① 初始化:生成0-99的随机数
        int number = (int)(Math.random() * 100);
        
        // 提示用户输入初始猜测值
        System.out.print("请输入猜测的数字:");
        Scanner scanner = new Scanner(System.in);
        int guess = scanner.nextInt();
        
        // ② 循环条件:猜测值不等于目标值
        while (guess != number) {
            // ③ 循环体:根据大小提示用户
            if (guess > number) {
                System.out.println("你猜的数字太大了");
            } else {
                System.out.println("你猜的数字太小了");
            }
            // ④ 迭代:读取新的猜测值
            System.out.print("请再次输入猜测的数字:");
            guess = scanner.nextInt();
        }
        
        // 循环终止:猜对提示
        System.out.println("恭喜你,猜对了");
        scanner.close();
    }
}

案例3:多个减法测试题(固定5题)

需求:生成 5 道减法题(确保被减数 ≥ 减数),统计正确和错误的题目数量。

package com.loop;

import java.util.Scanner;

/**
 * @Author Jing61
 * 功能:5道减法测试题,统计正确率
 */
public class SubstractionQuizLoop {
    public static void main(String[] args) {
        // ① 初始化:题目总数、计数器、正确题数
        final int NUMBER_OF_QUESTION = 5; // 固定5题(常量)
        int count = 0; // 已答题数计数器
        int correctCount = 0; // 正确题数计数器
        Scanner input = new Scanner(System.in);
        
        // ② 循环条件:答题数 < 总题数
        while (count < NUMBER_OF_QUESTION) {
            // 生成两个0-9的随机数
            int number1 = (int)(Math.random() * 10);
            int number2 = (int)(Math.random() * 10);
            
            // 确保被减数 ≥ 减数(交换两个数)
            if (number2 > number1) {
                int temp = number1;
                number1 = number2;
                number2 = temp;
            }
            
            // ③ 循环体:提示问题并读取答案
            System.out.println(number1 + " - " + number2 + " = ");
            int answer = input.nextInt();
            
            // 判断答案是否正确,更新正确题数
            if (answer == (number1 - number2)) {
                System.out.println("回答正确");
                correctCount++;
            } else {
                System.out.println("回答错误");
            }
            
            // ④ 迭代:计数器自增(已答题数+1)
            count++;
        }
        
        // 循环终止:输出统计结果
        System.out.println("你回答正确数目:" + correctCount);
        System.out.println("你回答错误数目:" + (NUMBER_OF_QUESTION - correctCount));
        input.close();
    }
}

标记值控制循环(不确定次数的循环)

当循环次数不确定时,可通过标记值(如输入 0 退出)控制循环终止,典型场景为“计算不确定个数的整数之和”。

案例:读取整数求和(输入0退出)

package com.loop;

import java.util.Scanner;

/**
 * @Author Jing61
 * 功能:计算不确定个数的整数之和,输入0时退出
 */
public class SentineValue {
    public static void main(String[] args) {
        // ① 初始化:输入流、初始数字、总和
        Scanner input = new Scanner(System.in);
        System.out.println("请输入你要计算求和的数,0退出");
        int num = input.nextInt(); // 读取第一个数字(标记值候选)
        int sum = 0; // 总和初始化为0
        
        // ② 循环条件:输入的数字不是标记值(0)
        while (num != 0) {
            // ③ 循环体:将当前数字加入总和
            sum += num;
            // ④ 迭代:提示并读取下一个数字
            System.out.println("请输入你要计算求和的数,0退出");
            num = input.nextInt();
        }
        
        // 循环终止:输出总和
        System.out.println("所有输入数字的和为:" + sum);
        input.close();
    }
}

说明:标记值(如 0)需与业务数据区分,避免误判(例如若计算正数和,0 适合作为标记值;若计算所有整数和,需选择其他标记值如 -1)。

for 循环

for 循环将“初始化、条件判断、迭代”整合在同一行,结构更紧凑,适合循环次数已知的场景(如遍历固定范围的数字)。

语法格式

for (① 初始化部分; ② 循环条件部分; ④ 迭代部分) {
    ③ 循环体部分(条件为true时执行)
}

执行顺序:①(仅一次)→ ②(判断)→ ③(条件满足时)→ ④ → ② → ... → ②(条件不满足,循环终止)

典型案例

案例1:穷举法求最大公约数(GCD)

需求:输入两个整数,用穷举法(从 2 到两数最小值遍历)寻找最大公约数。

package com.loop;

import java.util.Scanner;

/**
 * @Author Jing61
 * 功能:穷举法求两个整数的最大公约数(GCD)
 */
public class GreatestCommonDivisor {
    public static void main(String[] args) {
        // 提示用户输入两个整数
        System.out.println("请输入两个整数");
        Scanner input = new Scanner(System.in);
        int num1 = input.nextInt();
        int num2 = input.nextInt();
        
        // 初始化:两数的最小值(穷举的上限)、默认公约数为1
        int flag = Math.min(num1, num2); // Math.min(a,b) 返回a和b中的较小值
        int gcd = 1; // 最大公约数初始化为1
        
        // for循环:①初始化k=2;②条件k≤flag;④k自增
        for (int k = 2; k <= flag; k++) {
            // ③ 循环体:判断k是否为两数的共同公约数
            if (num1 % k == 0 && num2 % k == 0) {
                gcd = k; // 更新最大公约数
            }
        }
        
        // 循环终止:输出结果
        System.out.println(num1 + "和" + num2 + "的最大公约数是:" + gcd);
        input.close();
    }
}

说明:穷举法效率较低(时间复杂度 O(min(num1,num2))),优化解为欧几里得算法(辗转相除法,时间复杂度 O(log(min(num1,num2)))),此处仅作 for 循环演示。

案例2:打印101-2100年的闰年(每行10个)

需求:遍历 101-2100 年,筛选闰年并格式化输出(每行10个,制表符分隔)。

package com.loop;

/**
 * @Author Jing61
 * 功能:打印101-2100年的所有闰年,每行10个
 */
public class PrintLeapYear {
    public static void main(String[] args) {
        int res = 0; // 计数器:记录当前行已打印的闰年个数
        
        // for循环:①初始化i=101;②条件i<2100;④i自增(遍历每一年)
        for (int i = 101; i < 2100; i++) {
            // ③ 循环体:判断是否为闰年(闰年规则:能被4整除但不能被100整除,或能被400整除)
            if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
                System.out.printf("%d\t", i); // 制表符分隔,格式统一
                res++; // 计数器自增
                
                // 每行打印10个后换行,并重置计数器
                if (res == 10) {
                    System.out.println(); // 换行
                    res = 0; // 重置为0,开始新行
                }
            }
        }
    }
}

do-while 循环

do-while 循环是“先执行,后判断”的结构,循环体至少执行一次(无论初始条件是否满足),适合“必须执行一次”的场景(如用户输入验证、菜单交互)。

语法格式

// ① 初始化部分(仅执行一次)
do {
    ③ 循环体部分(至少执行一次)
    ④ 迭代部分(更新循环变量)
} while (② 循环条件部分); // 注意末尾的分号

执行顺序:① → ③ → ④ → ②(判断)→ ③(条件满足时)→ ④ → ... → ②(条件不满足,循环终止)

与 while 循环的核心区别

特性 while 循环 do-while 循环
执行逻辑 先判断,后执行 先执行,后判断
循环体执行次数 0 次或多次(条件不满足时0次) 1 次或多次(至少1次)
适用场景 循环次数可能为0的场景 必须执行一次的场景

示例:读取整数求和(至少输入一次)

需求:计算用户输入的整数之和,输入0退出(确保至少读取一次输入)。

package com.loop;

import java.util.Scanner;

/**
 * @Author Jing61
 * 功能:do-while实现整数求和,至少输入一次
 */
public class DoWhileSum {
    public static void main(String[] args) {
        // ① 初始化:总和、输入流
        int sum = 0;
        int num;
        Scanner input = new Scanner(System.in);
        
        // do-while循环:先执行一次循环体
        do {
            // ③ 循环体:提示并读取输入
            System.out.println("请输入一个整数(输入0退出):");
            num = input.nextInt();
            sum += num; // 将输入的数加入总和(0也会被加入,但不影响结果)
            
            // ④ 迭代:num已更新为新输入值
        } while (num != 0); // ② 循环条件:输入不是0则继续
        
        // 循环终止:输出总和
        System.out.println("所有输入数字的和为:" + sum);
        input.close();
    }
}

说明:若用户首次输入0,循环体仍会执行一次(读取0并加入总和,最终输出0),符合“至少输入一次”的需求;若用 while 循环,首次输入0会直接终止,无法读取任何输入。

嵌套循环

嵌套循环指“循环体内包含另一个循环”,外层循环控制“行数”或“大周期”,内层循环控制“列数”或“小周期”,常见于二维数据处理(如打印图案、矩阵运算)。

核心逻辑

  • 外层循环:每执行一次,内层循环会完整执行一遍(从初始条件到终止条件)。
  • 执行顺序:外层循环初始化 → 外层条件判断 → 内层循环完整执行 → 外层迭代 → 外层条件判断 → ...

典型案例:打印5×5星号图案

需求:打印 5 行 5 列的星号(*),每行 5 个,共 5 行。

package com.loop;

/**
 * @Author Jing61
 * 功能:嵌套循环打印5×5星号图案
 */
public class MultiLoop {
    public static void main(String[] args) {
        // 外层循环:控制行数(5行)
        for (int i = 0; i < 5; i++) {
            // 内层循环:控制列数(每行5个*)
            for (int j = 0; j < 5; j++) {
                System.out.print('*'); // 不换行,连续打印*
            }
            System.out.println(); // 内层循环结束后换行,开始下一行
        }
    }
}

输出结果

*****
*****
*****
*****
*****

执行过程解析

  1. 外层 i=0 → 内层 j=0j=4(打印5个*)→ 换行 → 外层 i=1
  2. 外层 i=1 → 内层 j=0j=4(打印5个*)→ 换行 → 外层 i=2
  3. 以此类推,直到外层 i=5(条件 i<5 不满足),循环终止。

扩展案例:打印直角三角形星号图案

需求:打印 5 行直角三角形,第 1 行 1 个 *,第 2 行 2 个 *,...,第 5 行 5 个 *

package com.loop;

/**
 * @Author Jing61
 * 功能:嵌套循环打印直角三角形星号图案
 */
public class RightTriangle {
    public static void main(String[] args) {
        // 外层循环:控制行数(5行)
        for (int i = 1; i <= 5; i++) {
            // 内层循环:控制列数(第i行打印i个*)
            for (int j = 1; j <= i; j++) {
                System.out.print('*');
            }
            System.out.println(); // 换行
        }
    }
}

输出结果

*
**
***
****
*****

循环控制语句(break、continue、return)

循环控制语句用于改变循环的默认执行流程,包括 break(终止循环)、continue(跳过本次循环)和 return(终止方法)。

break:终止当前循环

  • 作用:立即跳出 break 所在的循环(仅当前循环,不影响外层循环),执行循环后的代码。
  • 适用场景:找到目标值后提前终止循环(如判断回文数、筛选素数)。
  • 标记用法:若嵌套循环需终止外层循环,可给外层循环加标记(标识符+冒号),break 标记名 直接跳出标记对应的循环。

示例1:判断回文串(找到不匹配字符即终止)

回文串指“正读和反读一致的字符串”(如“abba”“上海自来水来自海上”),通过首尾指针对比,找到不匹配字符即终止循环。

package com.loop;

import java.util.Scanner;

/**
 * @Author Jing61
 * 功能:判断输入的字符串是否为回文串
 */
public class Palindrome {
    public static void main(String[] args) {
        System.out.println("请输入一个字符串:");
        Scanner input = new Scanner(System.in);
        String str = input.nextLine();
        
        // 初始化:首尾指针(low从0开始,high从最后一个字符开始)
        int low = 0;
        int high = str.length() - 1; // str.length() 返回字符串长度
        boolean isPalindrome = true; // 标记是否为回文串
        
        // 循环:首尾指针向中间移动,对比字符
        while (low < high) {
            // 若首尾字符不匹配,标记为非回文串并终止循环
            if (str.charAt(low) != str.charAt(high)) { 
                // str.charAt(n):返回字符串第n个字符(索引从0开始)
                isPalindrome = false;
                break; // 跳出当前while循环(无需继续对比后续字符)
            }
            // 指针移动(迭代)
            low++;
            high--;
        }
        
        // 输出结果
        if (isPalindrome) {
            System.out.println(str + "是一个回文串");
        } else {
            System.out.println(str + "不是一个回文串");
        }
        
        input.close();
    }
}

示例2:打印前50个素数(找到约数即终止内层循环)

素数指“大于1且仅能被1和自身整除的整数”,通过内层循环判断是否有其他约数,找到约数即终止内层循环(该数不是素数)。

package com.loop;

/**
 * @Author Jing61
 * 功能:打印前50个素数,每行10个
 */
public class PrimeNumber {
    public static void main(String[] args) {
        final int NUMBER_MAX = 50; // 目标素数个数(50个)
        int count = 0; // 已找到的素数个数
        int number = 2; // 从2开始判断(最小的素数)
        int lineCount = 0; // 每行打印的素数个数(控制换行)
        
        // 外层循环:找到50个素数为止
        while (count < NUMBER_MAX) {
            boolean isPrime = true; // 标记当前数是否为素数
            
            // 内层循环:判断number是否为素数(只需判断到sqrt(number),优化效率)
            for (int i = 2; i <= Math.sqrt(number); i++) {
                if (number % i == 0) { // 若能被i整除,不是素数
                    isPrime = false;
                    break; // 跳出当前for循环(无需继续判断其他约数)
                }
            }
            
            // 若为素数,计数并打印
            if (isPrime) {
                count++; // 素数总数+1
                lineCount++; // 当前行素数个数+1
                System.out.print(number + " ");
                
                // 每行打印10个后换行,重置行计数器
                if (lineCount == 10) {
                    System.out.println();
                    lineCount = 0;
                }
            }
            
            number++; // 迭代:判断下一个数
        }
    }
}


#### 示例3:标记break(终止外层循环)
嵌套循环中,默认 `break` 仅终止内层循环,若需终止外层循环,需给外层循环加标记:

```java
package com.loop;

/**
 * @Author Jing61
 * 功能:标记break示例,终止外层循环
 */
public class LabeledBreak {
    public static void main(String[] args) {
        // 给外层循环加标记:outer(遵循标识符命名规则)
        outer:
        for (int i = 1; i <= 3; i++) { // 外层循环:3行
            for (int j = 1; j <= 3; j++) { // 内层循环:3列
                if (i == 2 && j == 2) {
                    // 跳出标记为outer的外层循环(而非仅内层循环)
                    break outer; 
                }
                System.out.printf("(%d,%d) ", i, j);
            }
            System.out.println(); // 换行
        }
    }
}

解析:当 i=2j=2 时,break outer 直接跳出外层循环,不再执行后续的 (2,2)(2,3)i=3 的循环。

continue:跳过本次循环

  • 作用:跳过 continue 所在循环的“本次剩余代码”,直接进入下一次循环的条件判断(不终止循环,仅跳过当前次)。
  • 适用场景:筛选符合条件的元素(如打印偶数、跳过负数)。
  • 执行逻辑
    • while 循环:continue → 直接执行“循环条件判断”;
    • for 循环:continue → 先执行“迭代部分”,再执行“循环条件判断”;
    • 嵌套循环:仅跳过当前循环的本次,不影响外层循环。

示例1:打印1-100的偶数(跳过奇数)

package com.loop;

/**
 * @Author Jing61
 * 功能:用continue打印1-100的偶数
 */
public class ContinueEven {
    public static void main(String[] args) {
        for (int i = 1; i <= 100; i++) {
            // 若为奇数,跳过本次循环的剩余代码(不执行System.out)
            if (i % 2 != 0) {
                continue; 
                // for循环中,continue后会先执行迭代(i++),再判断条件
            }
            // 仅偶数会执行此打印语句
            System.out.print(i + " ");
        }
    }
}

输出结果

2 4 6 8 ... 98 100

执行逻辑

  • i 为奇数(如3):i%2!=0true,执行 continue,跳过 System.out,直接执行 i++(迭代),再判断 i<=100
  • i 为偶数(如4):i%2!=0false,不执行 continue,执行 System.out 打印偶数。

示例2:嵌套循环中的continue(跳过内层循环本次)

package com.loop;

/**
 * @Author Jing61
 * 功能:嵌套循环中continue的使用(跳过内层本次)
 */
public class NestedContinue {
    public static void main(String[] args) {
        // 外层循环:控制行数(3行)
        for (int i = 1; i <= 3; i++) {
            // 内层循环:控制列数(3列)
            for (int j = 1; j <= 3; j++) {
                // 跳过j=2的列(不打印该列)
                if (j == 2) {
                    continue; // 仅跳过内层循环的本次(j=2),不影响外层
                }
                System.out.printf("(%d,%d) ", i, j);
            }
            System.out.println(); // 换行
        }
    }
}

解析:内层循环中,j=2 时执行 continue,跳过 System.out,直接执行 j++(内层迭代),因此每一行都不打印 j=2 的列。

return:终止方法(含循环)

  • 作用return 用于方法中,功能是“返回值给方法调用者并终止当前方法”,若在循环中使用,会同时终止循环和方法(循环后的代码也不再执行)。
  • 语法
    • 无返回值方法(void):return;(无需带值,仅终止方法);
    • 有返回值方法(如 int/String):return 值;(返回指定值并终止方法)。

示例1:void方法中用return终止循环和方法

package com.loop;

/**
 * @Author Jing61
 * 功能:return在void方法中终止循环和方法
 */
public class ReturnVoid {
    public static void main(String[] args) {
        System.out.println("开始执行循环...");
        
        for (int i = 1; i <= 5; i++) {
            if (i == 3) {
                // 终止当前方法(main方法),循环和后续代码均不执行
                return; 
            }
            System.out.println("当前i值:" + i);
        }
        
        // 以下代码不会执行(被return跳过)
        System.out.println("循环结束");
    }
}

解析:当 i=3 时,return 终止 main 方法,循环不再继续,System.out.println("循环结束") 也不会执行。

示例2:有返回值方法中用return终止循环和返回值

package com.loop;

/**
 * @Author Jing61
 * 功能:return在有返回值方法中终止循环并返回结果
 */
public class ReturnWithValue {
    // 方法:查找数组中第一个偶数,找到则返回,未找到返回-1
    public static int findFirstEven(int[] arr) {
        for (int num : arr) { // 增强for循环遍历数组
            if (num % 2 == 0) {
                // 找到第一个偶数,返回该值并终止方法(循环也终止)
                return num; 
            }
        }
        // 遍历结束未找到偶数,返回-1
        return -1;
    }
    
    public static void main(String[] args) {
        int[] arr1 = {1, 3, 4, 5}; // 第一个偶数是4
        int[] arr2 = {1, 3, 5};    // 无偶数
        
        System.out.println("arr1的第一个偶数:" + findFirstEven(arr1)); // 输出4
        System.out.println("arr2的第一个偶数:" + findFirstEven(arr2)); // 输出-1
    }
}

输出结果

arr1的第一个偶数:4
arr2的第一个偶数:-1

解析:遍历 arr1 时,找到 4(偶数),return 4 终止 findFirstEven 方法并返回结果;遍历 arr2 时无偶数,循环结束后 return -1

break、continue、return 对比

语句 作用范围 对循环的影响 对方法的影响
break 当前循环(或标记循环) 终止当前循环,执行循环后代码 无影响
continue 当前循环 跳过本次循环,进入下一次 无影响
return 整个方法(含循环) 终止循环 终止方法,返回值(若有)
posted @ 2025-10-29 13:34  Jing61  阅读(33)  评论(0)    收藏  举报