1. Java循环高级综合练习概述
作为一名Java开发者,掌握循环结构是基本功中的基本功。但很多初学者在学完基础语法后,往往陷入"知道for/while怎么用,但遇到实际问题还是无从下手"的困境。今天我们就来通过一系列精心设计的综合练习,带你真正掌握Java循环的高级应用技巧。
这些练习不是简单的数字打印或求和,而是模拟真实开发场景中的典型问题。你将学会:
- 如何合理选择循环结构(for/while/do-while)
- 循环与条件判断的嵌套技巧
- 循环控制语句(break/continue)的实战应用
- 循环性能优化的常见思路
- 复杂业务逻辑的循环实现方案
2. 循环结构选择与优化
2.1 三种循环结构的适用场景
在Java中,我们有三种基本的循环结构:
- for循环:适合已知循环次数的场景
- while循环:适合循环次数不确定的场景
- do-while循环:适合至少执行一次的场景
实际开发中,90%的情况for循环就够用了,但另外10%的特殊场景,while和do-while能提供更优雅的解决方案。
2.1.1 for循环的进阶用法
传统for循环大家都会用,但很多人不知道可以这样写:
// 多变量控制的for循环 for(int i=0, j=10; i<j; i++, j--){ System.out.println("i="+i+", j="+j); } // 无限循环的for写法 for(;;){ // 循环体 if(condition) break; }2.1.2 while循环的陷阱与技巧
while循环最容易出现死循环问题,这里分享几个实用技巧:
// 标准写法 while(condition){ // 循环体 } // 带超时机制的while循环 long startTime = System.currentTimeMillis(); while(condition){ if(System.currentTimeMillis() - startTime > timeout){ throw new TimeoutException("操作超时"); } // 循环体 }2.2 循环性能优化实战
循环性能是Java开发中经常需要关注的点,特别是在大数据量处理时。以下是几个优化技巧:
减少循环内部计算:将不变的计算移到循环外部
// 优化前 for(int i=0; i<list.size(); i++){...} // 优化后 int size = list.size(); for(int i=0; i<size; i++){...}使用增强for循环:对于集合遍历更简洁高效
for(String item : stringList){ System.out.println(item); }避免在循环中创建对象:特别是大对象
// 错误示范 for(int i=0; i<1000; i++){ StringBuilder sb = new StringBuilder(); // 每次循环都新建 sb.append("Item ").append(i); System.out.println(sb.toString()); } // 正确做法 StringBuilder sb = new StringBuilder(); for(int i=0; i<1000; i++){ sb.setLength(0); // 清空原有内容 sb.append("Item ").append(i); System.out.println(sb.toString()); }
3. 循环与条件嵌套实战
3.1 多层嵌套的代码优化
循环与条件判断的嵌套是业务逻辑的常见实现方式,但过度嵌套会导致代码难以维护。这里分享几个解耦技巧:
// 优化前 - 嵌套过深 for(int i=0; i<100; i++){ if(i%2 == 0){ for(int j=0; j<50; j++){ if(j%3 == 0){ System.out.println(i + "-" + j); } } } } // 优化后 - 使用continue提前返回 for(int i=0; i<100; i++){ if(i%2 != 0) continue; for(int j=0; j<50; j++){ if(j%3 != 0) continue; System.out.println(i + "-" + j); } }3.2 复杂业务逻辑的实现
模拟一个真实场景:用户积分计算规则
- 每日登录获得5积分
- 连续登录每天额外获得2积分
- 每周登录满5天额外获得10积分
int[] loginDays = {1,1,1,0,1,1,1}; // 1表示登录,0表示未登录 int totalPoints = 0; int consecutiveDays = 0; int weeklyLoginCount = 0; for(int day : loginDays){ if(day == 1){ // 基础积分 totalPoints += 5; // 连续登录积分 consecutiveDays++; if(consecutiveDays >= 2){ totalPoints += 2; } // 周登录计数 weeklyLoginCount++; } else { consecutiveDays = 0; // 连续登录中断 } } // 周额外奖励 if(weeklyLoginCount >= 5){ totalPoints += 10; } System.out.println("总积分:" + totalPoints);4. 循环控制语句高级应用
4.1 break与continue的妙用
break和continue不只是简单的跳出和继续,它们可以大大简化复杂逻辑:
// 查找第一个满足条件的元素 int target = -1; for(int i=0; i<array.length; i++){ if(isValid(array[i])){ target = array[i]; break; // 找到后立即退出循环 } } // 跳过不符合条件的处理 for(int i=0; i<100; i++){ if(!shouldProcess(i)) continue; // 只处理符合条件的元素 processItem(i); }4.2 带标签的break和continue
这是Java中一个不太为人知但很有用的特性:
outerLoop: for(int i=0; i<10; i++){ for(int j=0; j<10; j++){ if(i*j > 50){ break outerLoop; // 直接跳出外层循环 } System.out.println(i + "*" + j + "=" + (i*j)); } }5. 常见问题与调试技巧
5.1 循环中的典型错误
死循环:最常见的是while循环条件永远为true
// 错误示范 while(true){ // 忘记添加退出条件 } // 正确做法 boolean running = true; while(running){ // 业务逻辑 if(shouldStop()){ running = false; } }循环变量错误:修改循环变量导致意外行为
for(int i=0; i<10; i++){ if(i == 5){ i = 8; // 直接跳到8,可能导致逻辑错误 } }
5.2 循环调试技巧
使用日志打印关键变量:
for(int i=0; i<array.length; i++){ System.out.println("i=" + i + ", value=" + array[i]); // 业务逻辑 }条件断点:在IDE中设置只在特定条件下触发的断点
循环计数器:复杂循环中添加计数器帮助分析
int loopCount = 0; while(condition){ loopCount++; if(loopCount > 1000){ System.out.println("可能陷入死循环"); break; } // 业务逻辑 }
6. 综合练习实战
现在我们来解决几个综合性的循环问题,检验学习成果:
6.1 素数判断与输出
编写程序输出1-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 + " "); } }6.2 数字金字塔
打印如下数字金字塔:
1 121 12321 1234321 123454321解决方案:
int n = 5; for(int i=1; i<=n; i++){ // 打印前导空格 for(int j=1; j<=n-i; j++){ System.out.print(" "); } // 打印左半部分 for(int j=1; j<=i; j++){ System.out.print(j); } // 打印右半部分 for(int j=i-1; j>=1; j--){ System.out.print(j); } System.out.println(); }6.3 模拟抽奖系统
实现一个抽奖系统,从100人中随机抽取5个不重复的获奖者
Random random = new Random(); Set<Integer> winners = new HashSet<>(); while(winners.size() < 5){ int candidate = random.nextInt(100) + 1; if(!winners.contains(candidate)){ winners.add(candidate); System.out.println("获奖者编号:" + candidate); } }7. 性能对比与最佳实践
7.1 不同循环方式的性能对比
我们通过一个简单的测试来比较几种循环方式的性能:
List<Integer> list = new ArrayList<>(); // 填充100万数据 for(int i=0; i<1_000_000; i++){ list.add(i); } // 测试1:传统for循环 long start = System.currentTimeMillis(); for(int i=0; i<list.size(); i++){ int val = list.get(i); } System.out.println("传统for循环耗时:" + (System.currentTimeMillis()-start) + "ms"); // 测试2:增强for循环 start = System.currentTimeMillis(); for(int val : list){ // do nothing } System.out.println("增强for循环耗时:" + (System.currentTimeMillis()-start) + "ms"); // 测试3:迭代器循环 start = System.currentTimeMillis(); Iterator<Integer> it = list.iterator(); while(it.hasNext()){ int val = it.next(); } System.out.println("迭代器循环耗时:" + (System.currentTimeMillis()-start) + "ms");测试结果会因环境而异,但通常增强for循环性能最优,特别是在ArrayList的情况下。
7.2 循环最佳实践总结
- 优先使用增强for循环:代码更简洁,性能通常也更好
- 避免在循环中做耗时操作:如IO操作、网络请求等
- 大数据量考虑分批次处理:不要一次性处理所有数据
- 复杂逻辑考虑拆分:不要把所有逻辑都塞进一个循环
- 合理使用并行流:Java 8+的parallelStream可以简化并行处理
// 并行处理示例 List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10); numbers.parallelStream().forEach(n -> { System.out.println(Thread.currentThread().getName() + "处理:" + n); });掌握这些循环高级技巧后,你会发现很多复杂的业务逻辑都能用简洁高效的循环来解决。记住,好的循环代码应该是易于理解、便于维护且性能良好的。