在java中我们处理一个集合中的数据常用的for循环直接处理这些数据。
for( int i = 0; i < list.size(); i++) {
if (list.get(i).startsWith("a")) {
tempList.add(list.get(i));
}
}
但是如果将所有操作 筛选、切片、映射、查找、去除重复,统计,匹配和归约,都写在for循环中必然会出现多重循环的情况,使得代码可读性很差的情况。那么采用流的形式就要清晰很多。
list.stream()
.filter(s -> s.startsWith("张"))
.filter(s -> s.length() == 3)
.forEach(System.out::println);
流就是像流水线一样执行各个操作,最终得到新的集合,如下图所示:


原理

ReferencePipeline 包含了控制数据流入的 Head ,中间操作 StatelessOp, StatefulOp,终止操作 TerminalOp。
Stream 常用的流操作包括:
- 中间操作(Intermediate Operations)
- 无状态(Stateless)操作:每个数据的处理是独立的,不会影响或依赖之前的数据。如
filter()、flatMap()、flatMapToDouble()、flatMapToInt()、flatMapToLong()、map()、mapToDouble()、mapToInt()、mapToLong()、peek()、unordered()等 - 有状态(Stateful)操作:处理时会记录状态,比如处理了几个。后面元素的处理会依赖前面记录的状态,或者拿到所有元素才能继续下去。如
distinct()、sorted()、sorted(comparator)、limit()、skip()等
- 无状态(Stateless)操作:每个数据的处理是独立的,不会影响或依赖之前的数据。如
- 终止操作(Terminal Operations)
- 非短路操作:处理完所有数据才能得到结果。如
collect()、count()、forEach()、forEachOrdered()、max()、min()、reduce()、toArray()等。 - 短路(short-circuiting)操作:拿到符合预期的结果就会停下来,不一定会处理完所有数据。如
anyMatch()、allMatch()、noneMatch()、findFirst()、findAny()等。
- 非短路操作:处理完所有数据才能得到结果。如
filter方法的源码:
@Override
public final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {
Objects.requireNonNull(predicate);
return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
}
@Override
public void accept(P_OUT u) {
if (predicate.test(u))
downstream.accept(u);
}
};
}
};
}
这些流操作当中实现了函数式接口的有哪几个?
map(Function<? super T, ? extends R> mapper):将流中的每个元素映射到另一个元素上,使用Function接口。filter(Predicate<? super T> predicate):根据给定的谓词过滤流中的元素,使用Predicate接口。forEach(Consumer<? super T> action):对流中的每个元素执行操作,使用Consumer接口。sorted(Comparator<? super T> comparator):根据比较器对流中的元素进行排序,使用Comparator接口。reduce(BinaryOperator<T> accumulator):通过某个连接动作将所有元素汇总成一个汇总结果,使用BinaryOperator接口。anyMatch(Predicate<? super T> predicate):如果流中至少有一个元素匹配给定的谓词,则返回true,使用Predicate接口。allMatch(Predicate<? super T> predicate):如果流中的所有元素都匹配给定的谓词,则返回true,使用Predicate接口。noneMatch(Predicate<? super T> predicate):如果流中没有元素匹配给定的谓词,则返回true,使用Predicate接口。findFirst():返回流中的第一个元素,如果流为空则返回一个空的Optional。findAny():返回流中的任意一个元素,如果流为空则返回一个空的Optional。collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner):将流转换成其他形式的结果,使用Supplier,BiConsumer接口。flatMap(Function<? super T, ? extends Stream<? extends R>> mapper):将流中的每个元素替换为目标流,然后将多个流连接到一个流,使用Function接口。
这些方法中的函数式接口允许你以声明式的方式处理集合,使得代码更加简洁和表达性强。通过传递Lambda表达式或方法引用,你可以轻松地实现这些接口。
参考文章;

Comments NOTHING