今天来聊聊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值
综合练习题
理论练习题
-
下面代码输出什么?
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
-
如何用嵌套循环打印5行星号,每行星号数量等于行号? 参考代码
for(int i=1; i<=5; i++) { for(int j=1; j<=i; j++) { System.out.print("*"); } System.out.println(); }
-
下面代码有什么问题?
int count = 0; for(int i=0; i<3; i++); { // 这里多了分号 for(int j=0; j<3; j++) { count++; } }
解析:外层循环后面误加分号,导致实际只执行空语句。
实战编程题
-
编写程序找出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
-
模拟超市商品库存管理系统:
- 支持多个商品类别的管理
- 每个类别下有多件商品
- 可以查询每个类别的商品总数
# 源文件保存为“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件
-
打印菱形图案:
解题思路:
- 分上下两部分处理
- 每行空格数+星号数=总行数
- 使用绝对值简化条件判断
# 源文件保存为“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(); } } }
嵌套循环就像处理复杂问题时的思维方式,先考虑大方向,再深入细节。掌握好这种"分而治之"的技巧,就能写出结构清晰、逻辑严密的代码。记住,写嵌套循环时要像剥洋葱一样,一层一层耐心处理,这样写出来的程序才会既正确又易于维护。