为什么不链接java.util.stream.stream#forEach 8中的代码> >代码> java .UTI.Struts。但为什么不呢?这不是链式函数。说它返回void而不是Streamit self
像这样为什么不链接java.util.stream.stream#forEach 8中的代码> >代码> java .UTI.Struts。但为什么不呢?这不是链式函数。说它返回void而不是Streamit self,java,java-8,Java,Java 8,像这样 Arrays .stream(Girls.toArray()) .forEach(Girls::getUp) .forEach(Girls::dressUp) .filter(/* Top 10 Girls */) .forEach(Gay.getMe()::gotGirl) .endFilter()// Not an API, but it means remove last filter .filter(/* Worst 10
Arrays
.stream(Girls.toArray())
.forEach(Girls::getUp)
.forEach(Girls::dressUp)
.filter(/* Top 10 Girls */)
.forEach(Gay.getMe()::gotGirl)
.endFilter()// Not an API, but it means remove last filter
.filter(/* Worst 10 Girls */)
.forEach(Gay.get(0)::gotGirl)
girls = Arrays
.stream(Girls.toArray());
girls.forEach(g->{g.getUp();g.dressUp()});
girls.filter(/* Top 10 Girls */)
.forEach(Gay.getMe()::gotGirl);
girls.filter(/* Worst 10 Girls */)
.forEach(Gay.get(0)::gotGirl);
第一个比第二个好,但是第一个的性能更差
那么,为什么
forEach
是不可链接的呢?您正在寻找的方法存在,并被调用和调用。使用Stream::peek
,上述代码可能如下所示
Arrays
.stream(Girls.toArray())
.peek(Girls::getUp)
.peek(Girls::dressUp)
.filter(/* Top 10 Girls */)
.peek(Gay.getMe()::gotGirl)
...
因为forEach是一个终端操作。它强制流使用其所有元素,并为每个元素调用使用者。一旦这样做了,流已经被消耗,并且不能被重用
一个流有您想要的任意多个中间操作,但只能有一个终端操作 forEach操作实际上是一个终端操作,因此不可链接,但可以将多个操作(在本例中为消费者)组合成一个
forEach
调用。例如:
Consumer<String> c1 = s -> System.out.println(s + "1");
Consumer<String> c2 = s -> System.out.println(s + "2");
Consumer<String> c3 = s -> System.out.println(s + "3");
Arrays.asList("a", "b", "c")
.stream()
.forEach(c1.andThen(c2).andThen(c3));
Consumer c1=s->System.out.println(s+“1”);
消费者c2=s->System.out.println(s+“2”);
消费者c3=s->System.out.println(s+“3”);
数组。asList(“a”、“b”、“c”)
.stream()
.forEach(c1.和第(c2).和第(c3));
不幸的是,如果没有一系列难看的转换,似乎不可能内联编写lambdas。使用
链接,然后确实是一种方法,但我们需要一些语法糖分来让它变得漂亮:
public class Consumers {
public static <T> Consumer<T> of(Consumer<T> base) {
return base;
}
}
或(较短):
(由于forEach可直接在该系列中使用)继续,可以内联写入lambdas,但只需强制转换第一个使用者:
Arrays.asList("a", "b", "c").forEach(
((Consumer<String>) s -> System.out.println(s + "1"))
.andThen(s->System.out.println(s + "2"))
.andThen(s -> System.out.println(s + "3"))
);
Arrays.asList(“a”、“b”、“c”).forEach(
((消费者)s->System.out.println(s+“1”))
.然后(s->System.out.println(s+“2”))
.然后(s->System.out.println(s+“3”))
);
As,然后在Java8中将
定义为
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
defaultconsumer,然后(consumerhowe,请注意,peek()
或map()
行为参数中可能干扰源或影响其他流操作结果的副作用是不允许的。peek()
方法实际上只是用于调试/记录日志,而不是用于计算结果;类似地,map()
应仅用于转换,而不是隐藏副作用。每次执行显式强制转换时,一个精灵就会死亡。
Arrays.asList("a", "b", "c").forEach(
((Consumer<String>) s -> System.out.println(s + "1"))
.andThen(s->System.out.println(s + "2"))
.andThen(s -> System.out.println(s + "3"))
);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
class CompositeConsumer<T> implements Consumer<T> {
private final List<Consumer<T>> funcs;
CompositeConsumer(List<Consumer<T>> funcs) {
this.funcs = funcs;
}
@Override
public void accept(T t) {
for (Consumer<T> func: funcs) {
func.accept(t);
}
}
}
List<Consumer<String>> funcs = ...
Arrays.asList("a", "b", "c")
.forEach(new CompositeConsumer(funcs));