什么是 Stream
Stream
是 Java 8 引入的一个新特性,位于 java.util.stream
包中。它提供了一种函数式编程风格的操作方式,用于处理集合数据。Stream
允许你以声明性方式(类似于 SQL 语句)处理数据,而不是通过命令式编程。
Stream
的特点
- 声明性:使用
Stream
可以以声明性方式处理数据,代码更简洁、可读性更高。 - 链式操作:
Stream
支持链式操作,可以将多个操作组合在一起。 - 惰性求值:
Stream
的中间操作是惰性求值的,只有在终端操作执行时才会实际处理数据。 - 并行处理:
Stream
支持并行处理,可以利用多核处理器的优势,提高性能。
创建 Stream
从集合创建
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
}
}
从数组创建
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
}
}
使用静态方法创建
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
Stream<String> stream = Stream.of("a", "b", "c");
}
}
Stream
的常用操作
中间操作
filter
:过滤元素。map
:将元素转换为另一种形式。flatMap
:将每个元素转换为一个流,然后将这些流合并为一个流。distinct
:去重。sorted
:排序。limit
:截取前 N 个元素。skip
:跳过前 N 个元素。
终端操作
forEach
:对每个元素执行操作。collect
:将流转换为其他形式(如集合)。reduce
:将流中的元素组合成一个值。count
:计算元素数量。anyMatch
、allMatch
、noneMatch
:匹配操作。findFirst
、findAny
:查找元素。
示例代码
使用 Stream
进行过滤和映射
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamExample {
public static void main(String[] args) {
List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
// 使用 Stream 进行过滤和映射
List<String> result = list.stream()
.filter(s -> s.startsWith("a"))
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(result); // 输出: [APPLE]
}
}
使用 Stream
进行聚合操作
import java.util.Arrays;
import java.util.List;
public class StreamExample {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// 使用 Stream 计算总和
int sum = list.stream()
.reduce(0, Integer::sum);
System.out.println("Sum: " + sum); // 输出: Sum: 15
}
}
Stream
与传统编程方式的区别
- 声明性:
Stream
提供了一种声明性编程方式,代码更简洁、可读性更高。例如,使用Stream
可以直接描述要做什么,而不是如何做。
List<String> result = list.stream()
.filter(s -> s.startsWith("a"))
.map(String::toUpperCase)
.collect(Collectors.toList());
- 命令式:传统编程方式是命令式的,需要明确地描述每一步操作。例如,使用循环和条件语句来实现相同的功能。
List<String> result = new ArrayList<>();
for (String s : list) {
if (s.startsWith("a")) {
result.add(s.toUpperCase());
}
}
链式操作 vs 分步操作
- 链式操作:
Stream
支持链式操作,可以将多个操作组合在一起,代码更简洁。
list.stream()
.filter(s -> s.startsWith("a"))
.map(String::toUpperCase)
.forEach(System.out::println);
- 分步操作:传统编程方式通常需要分步操作,每一步都需要单独处理。
for (String s : list) {
if (s.startsWith("a")) {
System.out.println(s.toUpperCase());
}
}
并行处理
- 并行处理:
Stream
支持并行处理,可以利用多核处理器的优势,提高性能。
list.parallelStream()
.filter(s -> s.startsWith("a"))
.map(String::toUpperCase)
.forEach(System.out::println);
- 传统处理:传统编程方式需要手动管理线程和同步,代码复杂度较高。
// 需要手动管理线程和同步
总结
Stream
:提供了一种函数式编程风格的操作方式,用于处理集合数据,支持声明性编程、链式操作、惰性求值和并行处理。- 传统编程方式:命令式编程,需要明确地描述每一步操作,代码可读性较低,难以并行处理。