Java Stream流
什么是流(Stream)?
流是 Java 8 引入的一种新特性,它为操作集合(如 List
、Set
)提供了一种更加声明性和函数式的方式。你可以把它看作是 对集合数据的处理管道。
与传统的基于循环(如 for
)的方式不同,流允许你以一种更简洁、更直观的方式来处理数据。流的一个核心思想就是:声明你想要做什么,而不需要关心如何去做(即不需要关心具体的实现细节)。
流可以做的事情包括:
流的组成部分
- 遍历集合。
- 过滤集合中的元素。
- 转换集合中的元素。
- 排序集合中的元素。
- 组合多种操作。
-
流的关键特性
- 惰性求值(Lazy Evaluation):流操作是惰性执行的,意味着它们不会立即执行,直到你调用终结操作(例如
collect()
、forEach()
)时才会开始实际的计算。 - 可以链式调用:流支持方法链的调用,你可以在一行代码中进行多种操作,如过滤、映射、排序等。
- 无副作用:流操作不会修改原始数据源,而是返回一个新的流或结果。
- 源(Source):流的起点,通常是一个集合(如
List
、Set
)、数组、文件等。 - 中间操作(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()); // 收集到一个列表中
流的方式相比传统方式更加简洁和声明性,代码更短,逻辑更加清晰。每个操作(如 filter
和 map
)都是链式调用,直接表达了你想要做什么:过滤、转换、收集。
流的工作原理
1. Stream 的源:
流通常来源于一个集合,如 List
、Set
、数组、甚至是文件等。例如,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)!