218. Java 函数式编程风格 - 从命令式风格到函数式风格:转换与迭代

36 阅读4分钟

218. Java 函数式编程风格 - 从命令式风格到函数式风格:转换与迭代

在前几篇文章中,我们讨论了如何将带有条件判断的命令式风格循环转换为函数式风格。在本篇文章中,我们将讨论如何将命令式风格的迭代,特别是涉及数据转换的迭代,转化为函数式风格。

🔄 数据转换与映射

在命令式风格中,当我们需要在迭代过程中转换数据时,通常会在循环体内执行一些数据变换操作。例如,假设我们有一个整数列表,我们想将每个整数加倍并打印出来。命令式风格的代码可能如下所示:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);

for (int number : numbers) {
    System.out.println(number * 2);  // 每个数字加倍后打印
}

在这个命令式的循环中,我们逐个迭代数字,并对每个数字执行乘以 2 的操作。要将这个操作转换为函数式风格,我们可以利用 map() 方法,它是函数式编程中进行数据转换的核心方法。


✨ 使用 map() 进行转换

在函数式风格中,我们使用 Stream 来处理数据,并使用 map() 方法来对流中的每个元素应用转换操作。map() 会返回一个新的流,流中的元素是经过转换后的数据。我们可以像这样重写上面的代码:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);

numbers.stream()  // 将列表转换为流
       .map(number -> number * 2)  // 对每个数字进行加倍转换
       .forEach(System.out::println);  // 打印转换后的结果

📚 详细解释:

  • stream():将集合转换为流。stream() 方法将数据从集合中提取出来,方便进行流式操作。
  • map(number -> number \* 2)map() 方法接收一个函数(在这里是一个 lambda 表达式),它会对流中的每个元素应用转换。在这个例子中,我们将每个数字乘以 2。
  • forEach(System.out::println)forEach() 方法用于遍历流中的每个元素,这里我们打印转换后的数字。

🎯 代码重构示例

对于数据转换的命令式代码,函数式风格的 map() 方法简洁且高效,不仅提高了可读性,还避免了显式的循环和条件判断,让代码更加简洁明了。


🔍 结合数据转换与条件筛选

在某些情况下,我们在数据转换之前需要先筛选一些元素。比如说,我们想把列表中的所有偶数加倍并打印。命令式代码可能像这样:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);

for (int number : numbers) {
    if (number % 2 == 0) {
        System.out.println(number * 2);  // 只有偶数才被加倍
    }
}

在这个命令式示例中,我们首先用 if 判断筛选出偶数,然后对筛选出的偶数进行加倍操作。

🎯 使用 filter()map() 结合实现

函数式风格的代码更加简洁。首先,我们使用 filter() 方法筛选出偶数,然后使用 map() 方法对筛选出的元素进行转换。代码如下:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);

numbers.stream()
       .filter(number -> number % 2 == 0)  // 筛选偶数
       .map(number -> number * 2)  // 对偶数进行加倍转换
       .forEach(System.out::println);  // 打印转换后的结果

📚 详细解释:

  • filter(number -> number % 2 == 0)filter() 方法用来筛选流中符合特定条件的元素。这里我们筛选出所有偶数。
  • map(number -> number \* 2):对筛选出的偶数进行加倍转换。
  • forEach(System.out::println):打印转换后的偶数。

🎯 映射总结

  1. 数据转换:任何时候我们在命令式循环中进行数据转换,都可以使用函数式风格的 map() 方法代替。这使得代码更加简洁,并且不需要显式管理迭代过程。
  2. 筛选与转换结合:如果我们既需要筛选数据又需要转换数据,函数式风格的 filter()map() 方法非常适用。filter() 用于条件筛选,map() 用于数据转换,两个方法可以串联在一起进行流式处理。

🌟 练习题

  1. 使用流的 map() 方法将一个字符串列表中的每个字符串转换为大写字母并打印出来。
  2. 使用流的 filter()map() 方法,从一个数字列表中筛选出所有正数,计算它们的平方并打印出来。

这些练习可以帮助学员更好地掌握如何在实际编码中使用流进行数据转换和筛选。通过这些练习,学员能够体会到函数式编程的优雅与简洁。