第6章 循环:让程序重复处理一批数据
如果程序只能执行一次逻辑,那它能做的事情很有限。真实任务里经常要重复:
- 输入多个学生成绩。
- 统计一组订单金额。
- 打印 1 到 100。
- 查找列表中是否有某个用户。
- 一直显示菜单,直到用户选择退出。
循环就是为了解决“重复执行”。
Java 中常见循环:
for- 增强
for whiledo while
还有两个重要控制语句:
breakcontinue
一、for 循环:已知次数时最常用
打印 1 到 5:
for(inti=1;i<=5;i++){System.out.println(i);}结构:
for (初始化; 循环条件; 每轮结束后执行) { 循环体 }执行顺序:
i++表示每次循环后 i 加 1。
常见写法:
for(inti=0;i<10;i++){System.out.println(i);}从 0 开始非常常见,因为数组和集合下标从 0 开始。
二、循环变量不是业务数据
for(inti=0;i<5;i++){System.out.println("第"+i+"次");}这里i是循环变量,它控制循环次数。
如果你要给用户看“第 1 次、第 2 次”,可以输出:
System.out.println("第"+(i+1)+"次");不要把下标和业务编号混淆。程序下标从 0 开始,人类编号通常从 1 开始。
三、求和:循环最经典的用途
求 1 到 100 的和:
intsum=0;for(inti=1;i<=100;i++){sum+=i;}System.out.println("总和:"+sum);sum += i等价于:
sum=sum+i;这种变量叫累计变量。循环中常见几类变量:
- 计数:
count - 求和:
sum - 最大值:
max - 最小值:
min - 是否找到:
found
四、遍历数组
int[]scores={90,85,70,60};for(inti=0;i<scores.length;i++){System.out.println(scores[i]);}关键是:
i<scores.length不能写:
i<=scores.length因为最后一个下标是scores.length - 1。
数组越界会报:
ArrayIndexOutOfBoundsException这是循环里最常见的错误。
五、增强 for:只读遍历更清楚
int[]scores={90,85,70,60};for(intscore:scores){System.out.println(score);}读法:对 scores 里的每一个 score。
适合:
- 不需要下标。
- 只读取每个元素。
- 做统计、打印、过滤判断。
不适合:
- 要修改数组某个位置。
- 要使用下标。
- 要倒序遍历。
修改数组应该用普通 for:
for(inti=0;i<scores.length;i++){scores[i]=scores[i]+5;}六、while:不知道循环次数时使用
while的意思是:只要条件成立,就一直执行。
intcount=3;while(count>0){System.out.println("倒计时:"+count);count--;}适合:
- 菜单一直显示,直到用户退出。
- 用户输入不合法,就继续要求输入。
- 读取文件直到结束。
- 等待某个条件发生。
死循环示例:
intcount=3;while(count>0){System.out.println(count);}count 没有变化,条件永远为 true。
写 while 时必须问:循环条件什么时候会变成 false?
七、do while:至少执行一次
intcount=0;do{System.out.println("至少执行一次");count++;}while(count<1);do while先执行,再判断。
它适合菜单:
intcommand;do{System.out.println("1. 查询");System.out.println("2. 添加");System.out.println("0. 退出");command=0;}while(command!=0);实际项目里for和while更常见,但do while对交互菜单很直观。
八、break:提前结束循环
查找第一个及格分数:
int[]scores={30,45,59,61,80};for(intscore:scores){if(score>=60){System.out.println("找到及格分数:"+score);break;}}break会直接结束整个循环。
适合:
- 找到目标后停止。
- 用户选择退出。
- 遇到无法继续的错误。
不要滥用 break。如果循环里有很多 break,说明流程可能需要拆方法。
九、continue:跳过本轮
打印所有及格分数:
int[]scores={30,80,50,90};for(intscore:scores){if(score<60){continue;}System.out.println("及格:"+score);}continue表示跳过本轮后面的代码,直接进入下一轮。
适合过滤无效数据:
String[]names={"Tom","",null,"Jack"};for(Stringname:names){if(name==null||name.isEmpty()){continue;}System.out.println("有效姓名:"+name);}这样主逻辑不会被包在很深的 if 里。
十、嵌套循环
打印乘法表:
for(introw=1;row<=9;row++){for(intcol=1;col<=row;col++){System.out.print(col+"x"+row+"="+(col*row)+"\t");}System.out.println();}外层控制行,内层控制列。
嵌套循环适合:
- 二维表格。
- 矩阵。
- 两两比较。
- 多层分类。
但嵌套循环成本高。两个 10000 长度的数据双层循环,就是一亿次比较。以后学集合和算法时会继续讲优化。
十一、循环实战:统计成绩
publicclassScoreLoopDemo{publicstaticvoidmain(String[]args){int[]scores={90,85,-1,70,120,60,45};intmax=0;intmin=100;intsum=0;intvalidCount=0;intpassCount=0;for(intscore:scores){if(score<0||score>100){System.out.println("忽略非法分数:"+score);continue;}if(score>max){max=score;}if(score<min){min=score;}if(score>=60){passCount++;}sum+=score;validCount++;}if(validCount==0){System.out.println("没有有效分数");return;}doubleaverage=sum*1.0/validCount;System.out.println("最高分:"+max);System.out.println("最低分:"+min);System.out.println("平均分:"+average);System.out.println("及格人数:"+passCount);}}这里用到了:
- 增强 for 遍历。
- continue 忽略非法数据。
- max/min/sum/count 累计。
- 计算平均值时避免整数除法。
- 没有有效数据时提前 return。
十二、循环实战:菜单重复显示
importjava.util.Scanner;publicclassMenuDemo{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);intcommand;do{System.out.println("==== 菜单 ====");System.out.println("1. 查询余额");System.out.println("2. 充值");System.out.println("3. 消费");System.out.println("0. 退出");System.out.print("请选择:");command=scanner.nextInt();switch(command){case1:System.out.println("余额:100元");break;case2:System.out.println("执行充值");break;case3:System.out.println("执行消费");break;case0:System.out.println("退出程序");break;default:System.out.println("未知命令");break;}}while(command!=0);}}这个例子是命令行程序的常见结构:菜单、输入、switch、循环。
后面阶段项目会继续使用这种结构。
十三、常见错误
1. 循环条件永远成立
while(true){System.out.println("停不下来");}有时你确实需要无限循环,但必须有 break 或外部退出条件。
2. 数组越界
for(inti=0;i<=scores.length;i++){System.out.println(scores[i]);}应写< scores.length。
3. 累计变量放错位置
for(intscore:scores){intsum=0;sum+=score;}sum 每轮都重新变成 0。应放在循环外。
4. continue 后面代码不执行
写 continue 前要确认本轮后续逻辑确实应该跳过。
5. 嵌套循环变量混乱
外层用 row,内层用 col,不要都叫 i。
十四、本章练习
用 for 打印 1 到 100。
计算 1 到 100 的和。
打印 1 到 100 中所有偶数。
给定数组:
int[]numbers={3,9,2,8,6,1};找出最大值和最小值。
- 写一个菜单程序,支持:
1. 打招呼 2. 显示时间占位文案 0. 退出- 打印九九乘法表。
十五、本章总结
循环用来重复执行逻辑。
你需要掌握:
- for 适合已知次数。
- 增强 for 适合只读遍历。
- while 适合未知次数。
- do while 至少执行一次。
- break 结束循环。
- continue 跳过本轮。
- 循环中常用 count、sum、max、min、found。
- 数组遍历条件通常是
i < array.length。 - 累计变量要放在循环外。
- 嵌套循环要注意可读性和性能。
下一章讲方法。方法会让我们把循环、条件、输入输出拆成更清晰的小块,为阶段项目做准备。