Java Stream 流的介绍
介绍
在 Java 8 中,引入了 Stream API,它为处理集合(如 List
、Set
等)提供了一种更简洁、声明式的方式。Stream 流的设计目标是支持对数据集合的高效操作,尤其是能够进行链式操作、并行处理等,极大地提升了代码的可读性和可维护性。
本文将介绍 Java Stream 流的基础概念、常用操作以及如何利用 Stream 进行集合数据处理。
1. 什么是 Stream 流
Stream 是 Java 8 引入的一个新的类,它代表了一个可以支持聚合操作的数据源(如集合、数组等),通过它我们可以以声明式的方式进行数据处理。Stream API 不是存储数据的结构,而是对数据进行操作的一个“管道”。
- Stream 并不存储数据:它只是在源数据上执行计算,计算的结果可能会生成一个新的集合或其他类型的数据。
- Stream 操作是惰性执行的:Stream 的操作会被延迟执行,直到遇到终止操作时才会触发实际计算。
- Stream 支持管道式操作:Stream 支持链式调用,通过多次组合各种操作,提供清晰和简洁的代码结构。
2. Stream 的类型
Stream 主要有两种类型:
- 顺序流(sequential Stream):默认情况下,Stream 操作是顺序执行的,即按照数据在源中的顺序逐个处理。
- 并行流(parallel Stream):通过并行计算加速流操作,通常用多核处理器进行任务分配,适用于计算密集型的操作。
3. Stream 的创建
Stream 的常见创建方式包括从集合、数组、文件、或者通过其他源生成流。
-
从集合创建:
List<String> list = Arrays.asList("apple", "banana", "cherry"); Stream<String> stream = list.stream();
-
从数组创建:
String[] array = {"apple", "banana", "cherry"}; Stream<String> stream = Arrays.stream(array);
-
通过 Stream 的静态方法创建:
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
-
通过文件创建:
Stream<String> lines = Files.lines(Paths.get("data.txt"));
4. Stream 操作
Stream API 提供了许多操作,分为中间操作和终止操作。
4.1 中间操作
中间操作返回一个新的 Stream,可以链式调用。中间操作通常是惰性求值的,只有在终止操作执行时才会真正执行。
常见的中间操作有:
-
map
:将每个元素映射成另一个元素,常用于转换数据格式。List<String> list = Arrays.asList("apple", "banana", "cherry"); List<Integer> lengths = list.stream() .map(String::length) .collect(Collectors.toList());
-
filter
:筛选符合条件的元素。List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); List<Integer> evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList());
-
sorted
:对流中的元素进行排序。List<Integer> numbers = Arrays.asList(5, 2, 4, 1, 3); List<Integer> sortedNumbers = numbers.stream() .sorted() .collect(Collectors.toList());
-
distinct
:去除重复的元素。List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4); List<Integer> distinctNumbers = numbers.stream() .distinct() .collect(Collectors.toList());
-
limit
:限制流中的元素数量。List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); List<Integer> limited = numbers.stream() .limit(5) .collect(Collectors.toList());
4.2 终止操作
终止操作会触发流的计算,并返回最终的结果。常见的终止操作有:
-
collect
:将流中的元素收集到集合中。List<String> list = Arrays.asList("apple", "banana", "cherry"); Set<String> set = list.stream() .collect(Collectors.toSet());
-
forEach
:对每个元素执行指定的操作。List<String> list = Arrays.asList("apple", "banana", "cherry"); list.stream() .forEach(System.out::println);
-
reduce
:将流中的元素反复结合起来,得到一个值,通常用于求和、求积等。List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, Integer::sum);
-
anyMatch
,allMatch
,noneMatch
:判断流中的元素是否符合某个条件。boolean anyMatch = numbers.stream() .anyMatch(n -> n > 3); // 检查是否有大于 3 的元素
-
findFirst
,findAny
:查找流中的第一个元素或任意一个元素。Optional<String> first = list.stream() .findFirst();
5. Stream 流的并行处理
Stream API 也支持并行流,通过 parallelStream()
或 stream().parallel()
可以创建并行流。并行流会尝试将流的操作分配给多个处理器核心,以并行的方式进行计算,通常适用于大规模的数据处理。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int sum = numbers.parallelStream()
.mapToInt(Integer::intValue)
.sum();
6. 使用 Stream 流的优势
- 简洁性和可读性:Stream API 提供了高阶的操作符,可以使代码更加简洁和富有表达力,尤其是处理复杂数据流时。
- 函数式编程:Stream API 基于函数式编程的思想,让你可以以声明式的方式处理数据,而不需要关注具体的迭代过程。
- 支持并行计算:Stream API 可以方便地利用多核处理器进行并行操作,提升处理效率。
7. 小结
Java 8 引入的 Stream API 使得集合数据的处理更加灵活、高效。它通过中间操作和终止操作,提供了丰富的功能,支持惰性计算和流式编程。此外,通过 parallelStream()
,你还可以轻松地并行处理数据,提升性能。无论是简单的数据处理还是复杂的流式操作,Stream API 都能帮助你写出简洁、易读且高效的代码。