一、Stream API 的核心概念
-
流(Stream) :
代表数据元素的序列,支持顺序或并行操作。
-
中间操作(Intermediate Operations) :
返回新流的操作(如
filter
,map
,sorted
),支持链式调用。 -
终端操作(Terminal Operations) :
触发流的遍历并生成结果(如
collect
,forEach
,reduce
)。
二、Stream 的创建方式
1. 从集合创建
java
List<String> list = Arrays.asList("apple", "banana", "cherry");
Stream<String> stream = list.stream(); // 顺序流
Stream<String> parallelStream = list.parallelStream(); // 并行流
2. 直接生成元素
java
Stream<String> stream = Stream.of("a", "b", "c");
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1); // 无限流
3. 从数组或文件生成
java
String[] array = {"a", "b", "c"};
Stream<String> arrayStream = Arrays.stream(array);
// 从文件生成流(逐行读取)
try (Stream<String> lines = Files.lines(Paths.get("data.txt"))) {
lines.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
三、常用中间操作
1. filter(Predicate<T>)
:过滤元素
java
List<String> filtered = list.stream()
.filter(s -> s.startsWith("a")) // 保留以 "a" 开头的字符串
.collect(Collectors.toList());
2. map(Function<T, R>)
:转换元素
java
List<Integer> lengths = list.stream()
.map(String::length) // 将字符串映射为其长度
.collect(Collectors.toList());
3. sorted()
/ sorted(Comparator<T>)
:排序
java
List<String> sorted = list.stream()
.sorted() // 自然排序
.collect(Collectors.toList());
List<String> customSorted = list.stream()
.sorted((s1, s2) -> s2.compareTo(s1)) // 自定义排序(逆序)
.collect(Collectors.toList());
4. distinct()
:去重
java
List<String> unique = list.stream()
.distinct()
.collect(Collectors.toList());
5. limit(n)
/ skip(n)
:截取或跳过元素
java
List<String> limited = list.stream()
.limit(2) // 取前2个元素
.collect(Collectors.toList());
四、常用终端操作
1. collect(Collector)
:将流转换为集合或其他结构
java
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
String joined = stream.collect(Collectors.joining(", "));
2. forEach(Consumer<T>)
:遍历元素
java
stream.forEach(System.out::println);
3. reduce()
:归约操作
java
Optional<String> concatenated = stream.reduce((s1, s2) -> s1 + s2);
int sum = Stream.of(1, 2, 3).reduce(0, Integer::sum);
4. count()
/ anyMatch()
/ allMatch()
/ noneMatch()
java
long count = stream.count();
boolean hasA = stream.anyMatch(s -> s.contains("a"));
五、并行流(Parallel Stream)
利用多核处理器加速处理:
java
List<String> result = list.parallelStream()
.filter(s -> s.length() > 3)
.collect(Collectors.toList());
六、Stream 的特性
-
不可复用:一个流只能被消费一次。
-
延迟执行:中间操作不会立即执行,直到触发终端操作。
-
链式调用:支持函数式编程风格。
七、示例:完整操作链
java
List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "fig");
List<String> result = words.stream()
.filter(s -> s.length() > 3) // 过滤长度>3的单词
.map(String::toUpperCase) // 转为大写
.sorted() // 按字母排序
.collect(Collectors.toList()); // 收集为List
System.out.println(result); // 输出 [APPLE, BANANA, CHERRY, DATE]
八、Stream vs 传统循环
特性 | Stream API | 传统循环(for/while) |
---|---|---|
代码风格 | 声明式(关注"做什么") | 命令式(关注"怎么做") |
并行支持 | 内置并行处理(parallelStream ) |
需手动实现多线程 |
可读性 | 链式调用,逻辑清晰 | 嵌套复杂时可能难读 |
性能 | 小数据量可能稍慢,大数据量优化 | 直接控制,通常更快 |
九、使用场景
-
适合 Stream :
数据过滤、转换、统计等函数式操作,尤其是需要并行处理的场景。
-
适合传统循环 :
需要直接控制迭代过程(如复杂条件中断、修改外部变量)。