自学内容网 自学内容网

Java Stream流

什么是流(Stream)?

流是 Java 8 引入的一种新特性,它为操作集合(如 ListSet)提供了一种更加声明性和函数式的方式。你可以把它看作是 对集合数据的处理管道

与传统的基于循环(如 for)的方式不同,流允许你以一种更简洁、更直观的方式来处理数据。流的一个核心思想就是:声明你想要做什么,而不需要关心如何去做(即不需要关心具体的实现细节)。

流可以做的事情包括:

流的组成部分

  • 遍历集合。
  • 过滤集合中的元素。
  • 转换集合中的元素。
  • 排序集合中的元素。
  • 组合多种操作。
  • 流的关键特性

  • 惰性求值(Lazy Evaluation):流操作是惰性执行的,意味着它们不会立即执行,直到你调用终结操作(例如 collect()forEach())时才会开始实际的计算。
  • 可以链式调用:流支持方法链的调用,你可以在一行代码中进行多种操作,如过滤、映射、排序等。
  • 无副作用:流操作不会修改原始数据源,而是返回一个新的流或结果。
  • 源(Source):流的起点,通常是一个集合(如 ListSet)、数组、文件等。
  • 中间操作(Intermediate Operations):对流中的元素进行转换或过滤,返回一个新的流。常见的中间操作有 filter()map()sorted() 等。
  • 终结操作(Terminal Operations):执行实际的计算,通常会产生一个结果。常见的终结操作有 collect()forEach()reduce() 等。

举个例子:传统方法 vs 流(Stream)

传统方法

假设你有一个 List,想要找出所有年龄大于 18 的用户,并将他们的名字转换为大写。

使用传统的 for-each 循环: 

List<User> users = getUsers();
List<String> result = new ArrayList<>();
for (User user : users) {
    if (user.getAge() > 18) {
        result.add(user.getName().toUpperCase());
    }
}

上面的代码,使用了显式的 for 循环,检查每个 User 是否符合条件,然后手动添加到结果列表中。

使用流(Stream)的方法

使用 来实现相同的操作:

List<String> result = users.stream()
    .filter(user -> user.getAge() > 18)  // 过滤出年龄大于18的用户
    .map(user -> user.getName().toUpperCase())  // 转换成大写
    .collect(Collectors.toList());  // 收集到一个列表中

流的方式相比传统方式更加简洁和声明性,代码更短,逻辑更加清晰。每个操作(如 filtermap)都是链式调用,直接表达了你想要做什么:过滤、转换、收集。

流的工作原理

1. Stream 的源

流通常来源于一个集合,如 ListSet、数组、甚至是文件等。例如,users.stream() 就是把 users 列表转成了一个流。

2. 中间操作

流的中间操作不会立即执行,它们会返回一个新的流对象。中间操作通常是用于变换流中的数据。常见的中间操作有:

  • map():转换每个元素(例如将字符串转换成大写)。
  • filter():过滤出符合条件的元素。
  • sorted():对流中的元素进行排序。
3. 终结操作

终结操作会触发流的实际计算,并且通常会产生一个结果。常见的终结操作有:

  • collect():将流中的元素收集到一个集合中。
  • forEach():对每个元素执行一个动作。
  • reduce():将流中的元素聚合成一个单一的结果。

forEach, reduce方法的解释

a. forEach():对每个元素执行一个动作

forEach() 是流的终结操作,用于遍历流中的每个元素,并对每个元素执行指定的操作。它常用于执行副作用(如打印、更新外部状态等)。

示例:
List<String> names = List.of("Alice", "Bob", "Charlie");
​
names.stream()
    .forEach(name -> System.out.println(name.toUpperCase()));

输出:

ALICE
BOB
CHARLIE

这里,forEach() 遍历 names 流的每个元素,将其转换为大写并打印。

b. reduce():将流中的元素聚合成一个单一的结果

reduce() 是流的终结操作,用于将流中的元素通过某种方式聚合成一个最终的结果,通常是通过一个二元操作符(例如加法、乘法等)。

示例:求和
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
​
int sum = numbers.stream()
    .reduce(0, (a, b) -> a + b);
​
System.out.println(sum);  // 输出 15
  • 起始值0 是聚合的初始值。

  • 累加器(a, b) -> a + b 是一个累加操作,它将流中的元素两两相加。

示例:连接字符串
List<String> words = List.of("Hello", "World", "Java");
​
String sentence = words.stream()
    .reduce("", (a, b) -> a + " " + b);
​
System.out.println(sentence);  // 输出 "Hello World Java"
  • 初始值:"" 是连接的起始字符串。

  • 累加器:(a, b) -> a + " " + b 用空格连接每个字符串。

总结
  • forEach():用于遍历流中的每个元素,并对每个元素执行某种操作(如打印、修改外部状态等)。

  • reduce():用于将流中的元素通过某种逻辑聚合成一个单一的结果,如求和、连接字符串等。


原文地址:https://blog.csdn.net/Blueis_oss/article/details/144331793

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!