214. Java 函数式编程风格 - Java 循环转换(二):带步长的循环如何函数式写法?
🧩 问题背景:当步长不是 1 时怎么办?
在上一节中,我们学会了如何用 IntStream.range() 来代替传统的简单 for 循环,例如:
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
可以优雅地转换为:
IntStream.range(0, 5)
.forEach(System.out::println);
但问题来了👇:
❓ 如果你想要步长为 2 呢?
比如:
for (int i = 0; i <= 10; i += 2) {
System.out.println(i);
}
这时 range() 就无法满足需求了。
✅ 正确方式:使用 IntStream.iterate()
Java 8 中的 IntStream.iterate() 是为这类需求准备的,它允许你自定义迭代逻辑。
🧪 示例:打印 0 到 10 的偶数
🟧 命令式:
for (int i = 0; i <= 10; i += 2) {
System.out.println(i);
}
🟩 JAVA 8函数式:
int start = 0, endInclusive = 10, step = 2;
int count = (endInclusive - start) / step + 1;
IntStream.iterate(start, i -> i + step)
.limit(count)
.forEach(System.out::println);
🟩 JAVA 9函数式:
Java 9 引入的三参 iterate(带终止条件)
IntStream.iterate(0, i -> i <= 10, i -> i + 2)
.forEach(System.out::println);
🎯 分解说明:
| 部分 | 说明 |
|---|---|
0 |
初始值 |
i -> i <= 10 |
终止条件 |
i -> i + 2 |
每次如何更新 |
🧠 误区提示
很多人初学时会想:“我可以先用 range() 生成所有值,再用 filter() 选出需要的。”
虽然这样能实现,但效率不如 iterate(),代码也不够直观:
IntStream.rangeClosed(0, 10)
.filter(i -> i % 2 == 0)
.forEach(System.out::println); // ✅可行,但不如 iterate 简洁表达“每次+2”
🔁 再来一个例子:从 5 开始,每次减1,直到大于 0
🟧 命令式:
for (int i = 5; i > 0; i--) {
System.out.println(i);
}
🟩 JAVA 8函数式:
int start = 5, endExclusive = 0, step = -1;
int count = (start - endExclusive); // 5,4,3,2,1 共 5 个
IntStream.iterate(start, i -> i + step)
.limit(count)
.forEach(System.out::println);
🟩 JAVA 9函数式:
IntStream.iterate(5, i -> i > 0, i -> i - 1)
.forEach(System.out::println);
💬 培训讲解小贴士
- 💡 把
iterate()当作“可编程 for 循环”,你可以定制起始值、结束条件、更新规则。 - 🎯 鼓励学员动手将“每次加 3”、“从 10 减到 0”、“每次乘以 2”等各种 for 循环尝试转写。
- ✅ 强调使用
iterate()时比range() + filter()更自然、更具表达力。
🧪 练习题建议
- 写一个从 1 到 20 的所有奇数打印出来的
iterate()实现。 - 转换一个每次乘以 2 的 for 循环为
IntStream.iterate()。 - 尝试用
iterate()实现一个倒计时功能(如从 10 到 0)。