Java Stream API 学习笔记

Java Stream API 学习笔记

一、 Stream API 概述

Stream API 是 Java 8 引入的强大功能,它为处理数据集合提供了一种新的范式。Stream API 可以简化代码,提高可读性,并充分利用多核处理器来提升性能。

二、 Stream API 的三大核心步骤

  1. Stream Creation (流的创建)

    • 流可以从多种数据源创建,包括集合、数组、文件、IO 通道等,甚至可以创建无限流。

    案例:

    简单案例: 从字符串列表创建流

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve", "Frank");
    Stream<String> nameStream = names.stream();
    

    复杂案例: 创建一个无限流,包含从 1 开始的奇数

    Stream<Integer> oddNumbers = Stream.iterate(1, n -> n + 2);
    
  2. Intermediate Operations (中间操作)

    • 中间操作用于对流中的元素进行处理,例如筛选、映射、排序等。
    • 中间操作是惰性执行的,这意味着它们不会立即执行,直到遇到终端操作才会实际执行。
    • 每个中间操作都会返回一个新的流,从而支持链式调用,可以构建复杂的数据处理管道。

    案例:

    简单案例: 筛选出年龄大于 18 岁的学生,并将他们的姓名转换为大写

    class Student {
        String name;
        int age;
        // 构造函数和 getter 方法
    }
    List<Student> students = Arrays.asList(
            new Student("Alice", 18),
            new Student("Bob", 20),
            new Student("Charlie", 16),
            new Student("David", 22)
    );
    Stream<String> adultNames = students.stream()
            .filter(student -> student.age > 18)
            .map(student -> student.name.toUpperCase());
    

    复杂案例: 将包含字符串列表的流转换为包含每个字符串中所有字符的流,并去重

    List<List<String>> wordGroups = Arrays.asList(
            Arrays.asList("a", "b", "c"),
            Arrays.asList("d", "e", "f"),
            Arrays.asList("g", "h", "i")
    );
    Stream<String> uniqueCharacters = wordGroups.stream()
            .flatMap(words -> words.stream())
            .distinct();
    
  3. Terminal Operations (终端操作)

    • 终端操作是整个流处理的实际执行部分,它会触发所有之前定义的中间操作,并生成最终结果。
    • 执行终端操作后,流中的元素会被消费,流就不能再次被使用了。

    案例:

    简单案例: 计算流中所有数字的平均值

      List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
      double average = numbers.stream().mapToInt(Integer::intValue).average().orElse(0.0);
    

    复杂案例: 将流中的元素收集到一个 Map 中,以元素的长度为键,元素列表为值

    List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
    Map<Integer, List<String>> wordsByLength = words.stream()
            .collect(Collectors.groupingBy(String::length));
    

三、 并行流

  • 默认情况下,创建的流都是顺序流,但也可以通过 parallel() 方法将顺序流转换为并行流。
  • 并行流可以借助多核处理器进行并行计算,从而提升数据处理的速度。

案例:

简单案例: 使用并行流计算字符串列表中所有字符串的长度总和

List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
int totalLength = words.stream().parallel().mapToInt(String::length).sum();

复杂案例: 使用并行流对一个大型文件中的所有单词进行排序,并打印前 10 个单词

try (Stream<String> lines = Files.lines(Paths.get("large_file.txt"))) {
    lines.parallel()
            .flatMap(line -> Arrays.stream(line.split("\\s+")))
            .sorted()
            .limit(10)
            .forEach(System.out::println);
} catch (IOException e) {
    // 处理异常
}

四、 重要注意事项

  • 流操作应该是链式调用的,即每次中间操作都应该基于前一次操作的结果,而不是重复使用同一个流实例进行多次操作。
  • 流本身并不是数据结构,它不会存储数据或改变数据源,它只定义了数据处理的流程。
  • 使用 Files.lines() 方法打开的文件资源必须被妥善关闭,以避免资源泄漏。为此,推荐将此操作封装在 try-with-resources 语句中,这样可以自动确保无论处理过程如何,文件资源都会被关闭。

五、 其他常用操作

  • Collectors 工具类提供了一系列静态方法,用于创建各种常用的收集器,例如 toList()toSet()toMap()groupingBy() 等。

案例:

简单案例: 使用 Collectors.toList() 将流中的元素收集到一个 List 中

List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
List<String> collectedWords = words.stream().collect(Collectors.toList());

复杂案例: 使用 Collectors.toMap() 将流中的元素收集到一个 Map 中,以元素本身为键,元素的长度为值

List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
Map<String, Integer> wordLengths = words.stream()
        .collect(Collectors.toMap(word -> word, word -> word.length()));
  • Optional 类型用于封装可能不存在的值,例如 findFirst()findAny() 方法返回的结果。

案例:

简单案例: 查找流中第一个长度大于 5 的字符串

List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
Optional<String> firstLongWord = words.stream().filter(word -> word.length() > 5).findFirst();
// 使用 ifPresent() 方法检查 Optional 是否存在值
firstLongWord.ifPresent(word -> System.out.println("First long word: " + word));

六、总结

Stream API 为 Java 程序员提供了一种更强大、更简洁、更高效的方式来处理数据集合。掌握 Stream API 的核心步骤和常用操作,可以帮助你编写更优雅、更易维护的代码。

  • 19
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值