Stream
是 Java 8 引入的一个非常强大的 API,它可以用来处理集合(如 List、Set 等)中的数据。Stream
提供了一种声明式的方式来处理集合的数据流,可以让你以更简洁、易读的方式编写代码。
1. 创建 Stream
可以通过以下几种方式创建一个 Stream:
- 从集合创建:可以直接从集合(如 List、Set)中获取 Stream。
List<String> list = Arrays.asList("a", "b", "c", "d");
Stream<String> stream = list.stream();
- 通过 Arrays 类创建:使用
Arrays.stream()
可以将数组转换成 Stream。
String[] array = {"a", "b", "c", "d"};
Stream<String> stream = Arrays.stream(array);
- 通过 Stream.of():通过
Stream.of()
创建包含一个或多个元素的流。
Stream<String> stream = Stream.of("a", "b", "c");
2. 常用操作
Stream 操作分为两类:中间操作 和 终端操作。
中间操作
中间操作是延迟计算的,它返回一个新的 Stream,因此可以链式调用。
filter
:根据给定的条件过滤元素。
Stream<String> filtered = stream.filter(s -> s.startsWith("a"));
map
:将元素应用于函数,转换成另一个类型或值。
Stream<String> mapped = stream.map(String::toUpperCase);
distinct
:去除重复元素。
Stream<String> distinct = stream.distinct();
sorted
:对元素进行排序。
Stream<String> sorted = stream.sorted();
limit
:限制流的元素个数。
Stream<String> limited = stream.limit(2); // 获取前两个元素
skip
:跳过指定数量的元素。
Stream<String> skipped = stream.skip(1); // 跳过第一个元素
终端操作
终端操作会触发流的计算,并且会消耗流。每个流只能执行一次终端操作。
forEach
:遍历流中的每个元素。
stream.forEach(System.out::println);
collect
:将流的元素收集到一个集合中。
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
reduce
:通过一个结合操作将流中的元素合并成一个单一的值。
Optional<String> result = stream.reduce((s1, s2) -> s1 + s2);
count
:返回流中元素的个数。
long count = stream.count();
anyMatch
、allMatch
、noneMatch
:检查流中的元素是否符合某些条件。
boolean result = stream.anyMatch(s -> s.startsWith("a"));
findFirst
:返回流中的第一个元素。
Optional<String> first = stream.findFirst();
findAny
:返回流中的任意一个元素。
Optional<String> any = stream.findAny();
3. 示例
import java.util.*;
import java.util.stream.*;
public class StreamExample {
public static void main(String[] args) {
// 创建一个List
List<String> list = Arrays.asList("apple", "banana", "cherry", "date", "fig", "grape");
// 使用Stream进行处理
list.stream()
.filter(s -> s.startsWith("a")) // 过滤出以"a"开头的元素
.map(String::toUpperCase) // 将元素转换为大写
.sorted() // 对元素进行排序
.forEach(System.out::println); // 输出结果
}
}
输出:
APPLE
4. 注意事项
- Stream 不可重复使用:Stream 一旦被消耗(例如执行了
forEach
或其他终端操作),它就不能再被使用。如果需要重复使用,需要重新创建 Stream。 - 懒加载:Stream 中的中间操作是懒加载的,只有在终端操作触发时才会开始执行。