217. Java 函数式编程风格 - 从命令式到函数式:基于条件选择元素
📝 命令式风格的 if
选择
假设在遍历集合时,我们想根据某个条件筛选出一些元素。比如,我们只希望打印出长度为 4
的名字。在命令式风格中,我们可以使用 if
语句来实现这一点,如下所示:
java
List<String> names = List.of("Jack", "Paula", "Kate", "Peter");
for (String name : names) {
if (name.length() == 4) {
System.out.println(name);
}
}
在这个命令式的例子中,我们遍历了 names
集合中的每个元素,并使用 if
判断条件来选择出符合条件(即长度为 4)的名字,然后打印出来。
🔄 转换为函数式风格
在函数式风格中,if
语句可以通过 Stream
的 filter()
方法来实现。filter()
方法会将满足条件的元素"放行",不满足条件的元素则会被丢弃。通过 filter()
,我们可以避免显式地使用 if
语句,使代码更加简洁和流畅。
将上面的命令式代码转换为函数式风格如下:
java
List<String> names = List.of("Jack", "Paula", "Kate", "Peter");
names.stream()
.filter(name -> name.length() == 4) // 过滤长度为 4 的名字
.forEach(System.out::println); // 打印符合条件的名字
💡 解释:
names.stream()
:我们先将集合转为流。filter(name -> name.length() == 4)
:filter()
方法接受一个谓词(Predicate
),它会检查每个元素是否满足条件。如果满足(即名字长度为 4),该元素将被传递到下一个操作,否则会被过滤掉。forEach(System.out::println)
:对每个符合条件的元素执行println
操作。
🧩 filter()
方法作为条件的替代
filter()
方法像一个过滤网,它决定哪些元素能通过,哪些会被丢弃。通过链式调用,我们可以轻松地在流中进行条件筛选。这种方法将 if
语句的条件判断内置在流操作中,使得代码更加简洁、清晰。
进一步的优化:更复杂的筛选条件
假设我们不仅仅想过滤出长度为 4
的名字,还想过滤出所有包含字母 a
的名字。我们可以将多个 filter()
操作链式调用,形成更复杂的条件筛选。
java
names.stream()
.filter(name -> name.length() == 4) // 先筛选长度为 4 的名字
.filter(name -> name.contains("a")) // 然后筛选包含字母 "a" 的名字
.forEach(System.out::println); // 打印符合条件的名字
解释 :通过链式调用的方式,先使用第一个
filter()
筛选出长度为 4 的名字,再通过第二个filter()
筛选出包含字母a
的名字,最终将所有符合这两个条件的名字打印出来。
📋 总结:命令式与函数式风格对比
命令式风格 | 函数式风格 |
---|---|
使用 for-each 循环和显式的 if 判断条件 |
使用 filter() 方法筛选符合条件的元素 |
迭代过程由程序员手动控制,条件判断显式 | 迭代过程由流的内部机制自动管理,条件判断内置于流操作中 |
代码较为冗长,尤其是当条件变复杂时 | 代码更加简洁、清晰,适合进行链式操作 |
🎯 结论
通过使用 filter()
方法,我们可以更优雅地进行条件筛选,而不再需要显式地使用 if
语句。将命令式风格转化为函数式风格后,代码变得更加简洁、易于维护,同时也更加符合流式编程的思维方式。