221. Java 函数式编程风格 - 从命令式风格到函数式风格:计算文件中包含指定单词的行数

221. Java 函数式编程风格 - 从命令式风格到函数式风格:计算文件中包含指定单词的行数

假设我们需要遍历一个文件,并计算包含指定单词的行数。下面是一个常见的命令式风格代码示例来完成这个任务:

🚨 命令式风格实现

// Sample.java
import java.nio.file.*;

public class Sample {
  public static void main(String[] args) {
    try {
       final String filePath = "src/main/java/chapter221/Sample.java";
       final String wordOfInterest = "public";

     try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
        String line = "";
        long count = 0;

        while((line = reader.readLine()) != null) {
          if(line.contains(wordOfInterest)) {
            count++;
          }
        }

        System.out.println(String.format("Found %d lines with the word %s", count, wordOfInterest));
      }
    } catch(Exception ex) {
      System.out.println("ERROR: " + ex.getMessage());
    }
  }
}

🧑💻 代码解析

在这段命令式代码中,我们执行了两个主要操作:

  1. 使用 BufferedReader 读取文件的内容。
  2. while 循环中检查每一行是否包含指定的单词。如果该行包含目标单词,就增加计数器。

我们可以看到,在 while 循环内有一个 if 条件判断,这通常是函数式风格中可以使用 filter() 方法的地方。接下来,我们将要探讨如何将这种命令式风格的代码转换为更加简洁且函数式的风格。

🔄 使用 Stream 转换数据

要使用函数式风格的流,我们首先需要将文件的内容转换为流数据。幸运的是,Java 早已提供了将文件内容转换为流的功能,这可以通过 Files.lines() 方法来实现。lines() 方法返回一个流,可以通过流操作(如 filter()count())来处理文件内容。

🧑💻 函数式风格实现

我们将前面的命令式风格代码转换为函数式风格,代码如下:

// Sample.java
import java.nio.file.*;

public class Sample {
  public static void main(String[] args) {
    try {
      final String filePath = "src/main/java/chapter221/Sample.java";
      final String wordOfInterest = "public";

      try (Stream<String> stream = Files.lines(Paths.get(filePath))) {
        long count = stream.filter(line -> line.contains(wordOfInterest))
          .count();

        System.out.println(String.format("Found %d lines with the word %s", count, wordOfInterest));
      }
    } catch(Exception ex) {
      System.out.println("ERROR: " + ex.getMessage());
    }
  }
}

🧑💻 代码解析

  1. Files.lines(Path.of(filePath)):此方法返回一个流,表示文件中的每一行。这是函数式编程的一个关键点,因为它允许我们将文件视作一个可以进行流操作的源,而不需要手动迭代每一行。
  2. filter(line -> line.contains(wordOfInterest)):在流中应用 filter() 方法,我们筛选出包含目标单词的行。
  3. count():使用 count() 方法对符合条件的行进行计数。
  4. try-with-resources:我们使用 try-with-resources 来确保流被正确关闭。

✨ 函数式风格带来的好处

通过将数据源(文件的每一行)转换为流,我们不仅简化了代码,还获得了以下好处:

  • 简洁性:代码变得更加简洁,去掉了复杂的循环和条件语句,直接用流操作来表达我们的意图。
  • 清晰性:函数式风格代码更加声明性,不需要我们手动管理迭代过程,流操作会自动处理。
  • 可读性:流式操作(如 filter()count())清晰地表达了我们对数据的处理逻辑,易于理解。

🛠 总结

  1. 函数式风格的优势:将命令式风格的代码转换为函数式风格后,代码更加简洁、可读且易于维护。我们通过将文件的每一行转换为流,利用 filter()count() 等流操作完成任务,而无需手动迭代文件内容。
  2. 流操作的核心概念:通过 Files.lines() 我们可以轻松地将外部数据源(如文件)转化为流,这样就可以像处理内存中的数据一样使用流的功能来处理外部资源。
  3. 提升效率和可维护性:函数式风格不仅使得代码更简洁,还能提升程序的可维护性,尤其是在需要处理大规模数据时,流的操作能高效地进行数据处理和资源管理。

通过这种方式,学员能够掌握如何将传统的命令式风格代码转换为现代的函数式风格代码,不仅提高代码质量,也提升了工作效率。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容