「Java流程控制」嵌套循环

0 阅读6分钟

今天来聊聊Java里的嵌套循环。这种结构就像俄罗斯套娃,大娃娃里面套着小娃娃,一层套一层。想象一下剥洋葱的过程,外层是整颗洋葱,内层是每一片洋葱瓣,这就是嵌套循环的生动写照。

嵌套循环工作方式

嵌套循环的工作方式特别像学校里的点名流程:

  • 外层循环:老师按班级顺序走(1班、2班、3班...)
  • 内层循环:在每个班级里,按学号顺序点名(1号、2号、3号...)

这种"大循环套小循环"的结构,特别适合处理有层次关系的数据。

基本语法结构

for(外层初始化; 外层条件; 外层迭代) {
    for(内层初始化; 内层条件; 内层迭代) {
        // 循环体
    }
}

这种结构就像工厂的生产线,外层是产品组装流程,内层是每个零件的加工步骤。

案例分析

九九乘法表

编写一个程序利用嵌套循环实现九九乘法表。

# 源文件保存为“MultiplicationTable.java”
public class MultiplicationTable {
    public static void main(String[] args) {
        System.out.println("九九乘法表:");
        
        for(int i = 1; i <= 9; i++) {        // 外层控制行数
            for(int j = 1; j <= i; j++) {     // 内层控制列数
                System.out.printf("%d×%d=%-2d ", j, i, i*j);  // 格式化输出
            }
            System.out.println();  // 换行
        }
    }
}

运行结果

九九乘法表: 1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
1×4=4 2×4=8 3×4=12 4×4=16 1×5=5 2×5=10 3×5=15 4×5=20 5×5=25 1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36 1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49 1×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=64 1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81

代码解析:

  • 外层循环变量i控制行数,从1到9
  • 内层循环变量j控制每行的列数,从1到当前行数i
  • printf格式化输出保持对齐,"%-2d"表示左对齐,占2位
  • 每行结束后换行

这个例子展示了嵌套循环处理二维问题的天然优势,就像写乘法表时先确定行再确定列一样自然。

学生成绩统计

编写一个程序,利用嵌套循环统计多个班级的学生成绩。

# 源文件保存为“GradeStatistics.java”
import java.util.Scanner;

public class GradeStatistics {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("请输入班级数量:");
        int classCount = scanner.nextInt();
        
        for(int classNo = 1; classNo <= classCount; classNo++) {
            System.out.printf("\n=== 第%d班 ===\n", classNo);
            System.out.print("请输入学生人数:");
            int studentCount = scanner.nextInt();
            
            double classTotal = 0;
            for(int studentNo = 1; studentNo <= studentCount; studentNo++) {
                System.out.printf("请输入学生%d的成绩:", studentNo);
                double score = scanner.nextDouble();
                classTotal += score;
            }
            
            double average = classTotal / studentCount;
            System.out.printf("第%d班的平均分:%.1f\n", classNo, average);
        }
        
        scanner.close();
    }
}

运行示例: 依次输入班级数,各班的人数和每个学生的成绩

请输入班级数量:2

=== 第1班 === 请输入学生人数:3 请输入学生1的成绩:85 请输入学生2的成绩:92 请输入学生3的成绩:78 第1班的平均分:85.0

=== 第2班 === 请输入学生人数:2 请输入学生1的成绩:88 请输入学生2的成绩:76 第2班的平均分:82.0

代码特点:

  • 外层循环处理各个班级
  • 内层循环处理每个班级的学生成绩
  • 清晰的层级结构,符合现实业务逻辑
  • 使用printf格式化输出,提升可读性

这个案例比简单的乘法表更贴近实际应用,展示了嵌套循环处理真实业务场景的能力。

常见错误与解决方法

循环变量混淆

for(int i=0; i<3; i++) {
    for(int i=0; i<3; i++) {  // 重复定义i
        System.out.println(i);
    }
}

解决方法:内外层循环变量不要重名,建议用有意义的变量名如row/col

死循环陷阱

for(int i=0; i<5; i++) {
    for(int j=0; j<5; i++) {  // 不小心把j++写成i++
        System.out.print("*");
    }
}

解决方法:检查内层循环的迭代条件,确保不会导致无限循环

性能问题

for(int i=0; i<list.size(); i++) {  // 每次循环都调用size()
    for(int j=0; j<list.size(); j++) {
        // 时间复杂度O(n²)
    }
}

解决方法:对于固定大小的集合,可以提前存储size值

综合练习题

理论练习题

  1. 下面代码输出什么?

    for(int i=1; i<=3; i++) {
        for(int j=1; j<=i; j++) {
            System.out.print(j + " ");
        }
        System.out.println();
    }
    

    运行结果

    1 1 2 1 2 3

  2. 如何用嵌套循环打印5行星号,每行星号数量等于行号? 参考代码

    for(int i=1; i<=5; i++) {
        for(int j=1; j<=i; j++) {
            System.out.print("*");
        }
        System.out.println();
    }
    
  3. 下面代码有什么问题?

    int count = 0;
    for(int i=0; i<3; i++); {  // 这里多了分号
        for(int j=0; j<3; j++) {
            count++;
        }
    }
    

    解析:外层循环后面误加分号,导致实际只执行空语句。

实战编程题

  1. 编写程序找出100以内的所有质数,使用嵌套循环实现

    # 源文件保存为“PrimeNumbers.java”
     public class PrimeNumbers {
         public static void main(String[] args) {
             System.out.println("100以内的质数:");
             for(int num = 2; num <= 100; num++) {
                 boolean isPrime = true;
                 for(int i=2; i<=Math.sqrt(num); i++) {
                     if(num % i == 0) {
                         isPrime = false;
                         break;
                     }
                 }
                 if(isPrime) {
                     System.out.print(num + " ");
                 }
             }
         }
     }
    

    运行结果

    100以内的质数: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

  2. 模拟超市商品库存管理系统:

    • 支持多个商品类别的管理
    • 每个类别下有多件商品
    • 可以查询每个类别的商品总数
    # 源文件保存为“PrimeNumbers.java”
    import java.util.Scanner;
    
    public class InventorySystem {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            
            System.out.print("请输入商品类别数量:");
            int categoryCount = scanner.nextInt();
            
            for(int cat = 1; cat <= categoryCount; cat++) {
                System.out.printf("\n=== 第%d类商品 ===\n", cat);
                System.out.print("请输入商品数量:");
                int itemCount = scanner.nextInt();
                
                System.out.println("请输入各商品名称:");
                for(int item = 1; item <= itemCount; item++) {
                    System.out.printf("商品%d:", item);
                    String name = scanner.next();
                    // 这里可以扩展存储商品信息
                }
                
                System.out.printf("第%d类商品共有%d件\n", cat, itemCount);
            }
            
            scanner.close();
        }
    }
    

    运行结果 依次输入商品类别数量、商品数量和商品名称

    请输入商品类别数量:3

    === 第1类商品 === 请输入商品数量:3 请输入各商品名称: 商品1:java 商品2:c# 商品3:Python 第1类商品共有3件

    === 第2类商品 === 请输入商品数量:2 请输入各商品名称: 商品1:方便面 商品2:炸酱面 第2类商品共有2件

    === 第3类商品 === 请输入商品数量:2 请输入各商品名称: 商品1:鞋子 商品2:袜子 第3类商品共有2件

  3. 打印菱形图案:

    在这里插入图片描述

    解题思路:

    • 分上下两部分处理
    • 每行空格数+星号数=总行数
    • 使用绝对值简化条件判断
    # 源文件保存为“Rhombus.java”
    public class Rhombus {
        public static void main(String[] args) {
            int size = 4;  // 上半部分行数
            for(int i=-size+1; i<size; i++) {
                int spaces = Math.abs(i);
                int stars = 2*(size - spaces) - 1;
                for(int s=0; s<spaces; s++) System.out.print(" ");
                for(int t=0; t<stars; t++) System.out.print("*");
                System.out.println();
            }
        }
    }
    
    

嵌套循环就像处理复杂问题时的思维方式,先考虑大方向,再深入细节。掌握好这种"分而治之"的技巧,就能写出结构清晰、逻辑严密的代码。记住,写嵌套循环时要像剥洋葱一样,一层一层耐心处理,这样写出来的程序才会既正确又易于维护。