最近在统计一批数据,经常要对一组数据进行过滤、筛选,最后聚合成一个新的集合,Java Stream API用的比较多,也发现一些规律有迹可循。
一、Java Stream API 简单梳理
Java Stream API 是 Java 8 引入的一个强大功能,目的是简化集合操作,支持声明式的处理数据。
Stream API 允许我们以流的方式处理集合数据,提供了更简洁、功能强大的操作方式,特别是在进行数据转换、过滤、汇总等复杂操作时。
1、Stream 的概念
Stream 并不是数据结构,它只是表示一种数据流,可以通过它对数据进行一系列操作。
Stream 是惰性的(lazy),即流中的操作(如过滤、映射等)不会立即执行,而是直到最终的终结操作(如 collect()、forEach() 等)触发时才会执行。
Stream 是一次性的,流中的数据只能被消费一次,消费后会自动关闭。
2、Stream 的主要特性
声明式处理:传统的集合操作通常使用迭代器或 for 循环显式地遍历数据,而 Stream API 使用声明式的方法链方式进行操作,更加简洁和易于理解。
支持并行处理:Stream API 支持并行流(parallelStream()),可以自动利用多核 CPU 的优势,对数据进行并行处理。
支持惰性求值:大部分操作都是惰性执行的,只有在需要结果时(例如 forEach 或 collect)才会触发计算。
流水线化:Stream 操作通常是链式调用,多个操作可以组成一个处理流水线。
3、Stream 的使用步骤
Java Stream Api的使用可以分为三步:
第一步,创建流
想使用流,就需要先创建流。
废话,创建流谁不会,集合点stream()方法就出来了。
我曾经也这样想,后来发现其他创建Stream的方法后,才发现,是我肤浅了。
第二步,中间操作(Intermediate Operations)
中间操作返回一个新的流,它们是惰性执行的,只有在终结操作触发时才会执行。
常见的中间操作包括:filter()、map()、distinct()、sorted()、peek() 等。
第三步,终端操作(Terminal Operations)
终端操作会触发流的计算,并且通常会产生一个结果(如集合、单个元素或数值等),且流会被关闭。
常见的终结操作包括:collect()、forEach()、reduce()、count()、anyMatch()、allMatch() 等。
二、创建流的6种方式
1. 从集合创建 Stream
Java 8 提供了一个非常简单的方式来从集合类(如 List、Set、Map 等)创建流。可以直接调用集合的 stream() 或 parallelStream() 方法来创建流。
import java.util.*;import java.util.stream.*;public class StreamExample { public static void main(String[] args) { // 从 List 创建 Stream List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Stream<Integer> numberStream = numbers.stream(); // 从 Set 创建 Stream Set<String> names = new HashSet<>(Arrays.asList("Alice", "Bob", "Charlie")); Stream<String> nameStream = names.stream(); // 从 Map 创建 Stream(按键或值) Map<String, Integer> map = new HashMap<>(); map.put("Alice", 25); map.put("Bob", 30); map.put("Charlie", 35); // 通过键集创建 Stream Stream<String> keyStream = map.keySet().stream(); // 通过值集创建 Stream Stream<Integer> valueStream = map.values().stream(); }}
2. 通过数组创建 Stream
Arrays.stream() 方法允许从数组创建流,无论是原始类型数组(如 int[]、double[] 等)还是引用类型数组(如 String[]、Integer[] 等)。
import java.util.Arrays;import java.util.stream.*;public class StreamExample { public static void main(String[] args) { // 从 int 数组创建 Stream int[] intArray = {1, 2, 3, 4, 5}; IntStream intStream = Arrays.stream(intArray); // IntStream 用于处理原始 int 类型 // 从引用类型数组创建 Stream String[] strArray = {"A", "B", "C"}; Stream<String> stringStream = Arrays.stream(strArray); }}
3. 通过 Stream.of() 创建 Stream
Stream.of() 是一个工厂方法,适用于创建包含多个元素的流,可以直接传递一组元素。
import java.util.stream.*;public class StreamExample { public static void main(String[] args) { // 创建一个包含多个元素的 Stream Stream<String> stringStream = Stream.of("Apple", "Banana", "Cherry"); // 还可以通过 Stream.of 创建其他类型的流 Stream<Integer> intStream = Stream.of(1, 2, 3, 4, 5); }}
4. 通过 Stream.iterate() 创建 Stream
Stream.iterate() 是一种创建无限流的方式。它从一个初始值开始,根据指定的规则生成后续的元素。iterate() 方法接收两个参数:初始值和生成下一个元素的规则。
import java.util.stream.*;public class StreamExample { public static void main(String[] args) { // 创建一个从 0 开始,每次增加 2 的无限流 Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2); // 通过 limit() 限制生成元素个数 evenNumbers.limit(5).forEach(System.out::println); // 输出 0, 2, 4, 6, 8 }}
5. 通过 Stream.generate() 创建 Stream
Stream.generate() 创建一个无限流,它从一个提供元素的 Supplier 函数开始生成元素。通常用于生成随机数、无限序列等。
import java.util.stream.*;public class StreamExample { public static void main(String[] args) { // 生成一个无限的随机数流 Stream<Double> randomNumbers = Stream.generate(Math::random); // 通过 limit() 限制生成元素个数 randomNumbers.limit(5).forEach(System.out::println); // 输出 5 个随机数 }}
6. 通过 Stream.concat() 合并两个流
Stream.concat() 方法可以将两个流合并成一个流,它接收两个流作为参数,返回一个合并后的流。
import java.util.stream.*;public class StreamExample { public static void main(String[] args) { // 创建两个流 Stream<String> stream1 = Stream.of("A", "B", "C"); Stream<String> stream2 = Stream.of("D", "E", "F"); // 合并两个流 Stream<String> combinedStream = Stream.concat(stream1, stream2); // 打印结果 combinedStream.forEach(System.out::println); // 输出 A, B, C, D, E, F }}
三、最后总结
在Java 中可以通过以下方式创建 Stream对象:
1. 从集合创建
使用 Collection.stream()或 Collection.parallelStream()。
2. 从数组创建
使用 Arrays.stream()。
3. 使用 Stream.of()
用于创建由多个元素组成的流。
4. 使用 Stream.iterate()
生成基于给定规则的元素流。
5. 使用 Stream.generate()
生成无限流(通常用于随机数等)。
6. 合并流
使用 Stream.concat() 合并两个流。
以上6种方式中,从集合中创建Stream是我们最常用的方法,其他方式知道就可以了。
领取专属 10元无门槛券
私享最新 技术干货