一、流式编程
在 Java 流式编程中,流(Stream)是一个抽象的概念,用于表示数据的序列。流提供了一种高级迭代的机制,允许你以声明式方式处理数据集合。
1.1.流式编程概述
流是一个元素序列,这些元素可以是集合中的元素,也可以是来自于数组、I/O通道、生成器函数等。
Stream流的作用是结合Lambda表达式,简化集合、数组的操作
对于Stream流的使用步骤总结成以下:
1.2.创建流
1. 从集合创建流
集合(如 List、Set)是最常见的流数据源。集合提供了 stream() 方法,直接用来创建流
List<String> words = Arrays.asList("apple", "banana", "cherry");
Stream<String> stream = words.stream(); // 创建流
注意如HashMap等双列集合没法直接用该方法
2. 从数组创建流
Java 提供了 Arrays.stream() 方法,用于从数组创建流。这个方法可以处理对象数组或基本类型数组
String[] fruits = {"apple", "banana", "cherry"};
Stream<String> stream = Arrays.stream(fruits);
3. 使用 Stream.of() 创建流
Stream<String> stream = Stream.of("apple", "banana", "cherry");
4、使用 Stream.iterate() 或generate()创建无限流
Stream.iterate() 方法用于创建一个无限流,它接受一个初始值和一个有返回值的函数,每次调用该函数来生成序列中的下一个元素
Stream<Long> infiniteStream = Stream.iterate(1, n -> n + 1);
最后常见获取流的几种方法总结成下表
单列集合 | default Stream<E> stream() | Collection中的默认方法 |
双列集合 | 无 | 无法直接使用stream流 |
数组 | public static<T> Stream<T> stream(T[] array) | Arrays工具类中的静态方法 |
一堆零散的数据 | public static<T> Stream<T> of(T... values) | Stream接口中的静态方法 |
需要注意的是:Stream接口中的of方法,它的形参是一个可变参数,除了可以传递零散数据还可以传递数组。但是数组必须是引用数据类型的,如果是基本数据类型是会把整个数组当作一个元素,放到Stream中。
二、流式操作
2.1.Stream流的中间方法
2.1.1.filter
filter(Predicate<? super T> predicate)筛选流中的元素,只有满足给定谓词的元素才会被保留在流中。
Stream<String> filteredStream = strings.stream().filter(s -> s.startsWith("a"));
2.1.2.limit
limit(long maxSize)截断流,使其最多包含给定数量的元素。
Stream<String> limitedStream = strings.stream().limit(2);
2.1.3.skip、distinct、concat
分别是skip(long n)跳过前几个元素,distinct()元素去重依赖(hashCode和equals方法)以及concat(Stream a,Stream b)合并a和b两个流为一个流。
2.1.4.map
map(Function<? super T,? extends R> mapper)将流中的每个元素映射到另一个元素上,返回一个新的流。
Stream<Integer> lengthStream = strings.stream().map(String::length);
2.2.Stream流的终结方法
2.2.1.forEach
forEach(Consumer<? super T> action)对流中的每个元素执行给定的操作。
stream.forEach(System.out::println); // 打印流中的每个元素
这里详细解释一下里面的Consumer<? super T> action,它 是一个函数式接口,它定义了一个 accept 方法,用于接收单个输入参数并执行某些操作。源码如下:
2.2.2.reduce
reduce()通过某个连接动作将所有元素汇总成一个汇总结果。
Optional<Integer> sum = stream.reduce((x, y) -> x + y); // 求和
2.2.3.toArray
toArray()将流中的元素收集到数组中。
Object[] array = stream.toArray(); // 将流转换为数组
注意:toArray方法的底层,会依次得到流里面的每一个数据,并把数据放到数组中。
2.2.4.收集方法collect
collect(Collector<? super T, A, R> collector)将流中的元素汇总到一个结果容器中。在 Java 的 Stream API 中,collect 方法是一个非常强大的终端操作。这个方法接受一个 Collector 对象作为参数,该对象定义了如何将流中的元素收集到一个特定的容器中。
List<T> list = stream.collect(Collectors.toList()); // 将流收集到列表
常用的 Collector 实现
Java 8 提供了一些常用的 Collector 实现,它们位于 java.util.stream.Collectors 类中。以下是一些常用的 Collector:
Collectors.toList()
:将流中的元素收集到一个List
中。Collectors.toSet()
:将流中的元素收集到一个Set
中。Collectors.toMap()
:将流中的元素收集到一个Map
中。Collectors.joining()
:将流中的元素连接成一个字符串。Collectors.summing()
:计算流中元素的总和。Collectors.maxBy()
:找到流中最大的元素。Collectors.groupingBy()
:根据某个属性将流中的元素分组。Collectors.partitioningBy()
:根据某个条件将流中的元素分为两组。