Java 中的流(Streams)
Java 中的流(Streams)是 Java 8 引入的一个强大功能,用于处理数据序列(如集合、数组等)的一系列操作。流提供了一种声明性的方法,可以使用函数式编程的风格来处理数据,而不是通过传统的迭代器或者循环。流的操作一般分为两类:中间操作(intermediate operations)和终端操作(terminal operations)。
1. 流的特点
- 无存储: 流不存储数据,而是从数据源(如集合、数组)中获取数据并以管道的方式处理。
- 惰性执行: 流的操作是惰性执行的,即只有在需要结果时才会执行。这意味着如果一个流没有终端操作,它的中间操作不会被执行。
- 不可改变性: 流的每次操作都会生成一个新的流,原始数据源不会被修改。
2. 流的创建
流可以通过以下几种方式创建:
通过集合: 通过调用集合接口的 stream() 方法或者 parallelStream() 方法来创建一个顺序流或并行流。
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
通过数组: 使用 Arrays.stream() 方法。
int[] numbers = {1, 2, 3, 4};
IntStream intStream = Arrays.stream(numbers);
通过静态工厂方法: 如 Stream.of() 方法。
Stream<String> stream = Stream.of("a", "b", "c");
通过生成流: 使用 Stream.generate() 或 Stream.iterate() 方法。
Stream<Double> randoms = Stream.generate(Math::random);
3. 中间操作
中间操作返回的是一个新的流,允许链式调用。常见的中间操作有:
filter(Predicate<? super T> predicate): 用于对流中的元素进行过滤,只保留满足条件的元素。
List<String> result = list.stream()
.filter(s -> s.startsWith("a"))
.collect(Collectors.toList());
map(Function<? super T, ? extends R> mapper): 用于将流中的元素映射为另一个类型。
List<Integer> lengths = list.stream()
.map(String::length)
.collect(Collectors.toList());
**sorted(Comparator<? super T> comparator):**对流中的元素进行排序。
List<String> sortedList = list.stream()
.sorted()
.collect(Collectors.toList());
distinct(): 去除流中的重复元素。
List<Integer> distinctNumbers = Arrays.asList(1, 2, 2, 3).stream()
.distinct()
.collect(Collectors.toList());
4. 终端操作
终端操作会触发流的执行,并返回一个结果。常见的终端操作有:
collect(Collector<? super T, A, R> collector): 将流中的元素收集到一个集合或其他容器中。
List<String> collectedList = list.stream()
.filter(s -> s.startsWith("a"))
.collect(Collectors.toList());
forEach(Consumer<? super T> action): 对流中的每个元素执行指定的动作。
list.stream().forEach(System.out::println);
**
forEach(Consumer<? super T> action): 对流中的元素进行累积操作,生成一个值。
int sum = Arrays.asList(1, 2, 3).stream()
.reduce(0, Integer::sum);
**count():**返回流中元素的数量。
long count = list.stream().filter(s -> s.startsWith("a")).count();
**findFirst() 和 findAny():**返回流中的第一个元素或任意元素。
Optional<String> first = list.stream().findFirst();
5. 流的并行处理
流可以通过并行流(Parallel Stream)来并行处理数据,这样可以充分利用多核处理器的能力来加快处理速度。使用 parallelStream() 方法创建一个并行流,或者使用 stream() 创建流后调用 parallel() 方法转换为并行流。
List<String> parallelProcessedList = list.parallelStream()
.filter(s -> s.startsWith("a"))
.collect(Collectors.toList());
6. 总结
流为 Java 提供了一种功能强大的方式来处理集合数据。通过流,您可以以声明式和函数式编程的方式对数据进行复杂的操作,代码更加简洁、可读性更强。流的惰性计算、不可变性以及并行处理能力使其在处理大数据集时非常高效。