Java8泛型:将消费者流减少为单个消费者
如何使用Java8泛型:将消费者流减少为单个消费者,java,generics,java-8,java-stream,Java,Generics,Java 8,Java Stream,如何使用消费者编写一种方法,将消费者的流组合成单个消费者。然后(消费者) 我的第一个版本是: <T> Consumer<T> combine(Stream<Consumer<T>> consumers) { return consumers .filter(Objects::nonNull) .reduce(Consumer::andThen) .orElse(noOp
消费者编写一种方法,将消费者的流
组合成单个消费者
。然后(消费者)
我的第一个版本是:
<T> Consumer<T> combine(Stream<Consumer<T>> consumers) {
return consumers
.filter(Objects::nonNull)
.reduce(Consumer::andThen)
.orElse(noOpConsumer());
}
<T> Consumer<T> noOpConsumer() {
return value -> { /* do nothing */ };
}
这是不可能编译的。改进后的版本将是:
<T> Consumer<T> combine(Stream<? extends Consumer<? super T>> consumers) {
return consumers
.filter(Objects::nonNull)
.reduce(Consumer::andThen)
.orElse(noOpConsumer());
}
(为了简洁起见,没有过滤空值。)
因此,我的问题是:如何让JavaC和Eclipse相信我的代码是正确的?或者,如果它不正确:为什么循环版本正确而流版本不正确?您忘记了方法定义中的一件小事。目前是:
<T> Consumer<T> combine(Stream<? extends Consumer<? super T>> consumers) {}
现在应该可以使用了您使用的是具有以下签名的单参数版本:
Optional<T> reduce(BinaryOperator<T> accumulator);
我建议您使用该方法的三参数版本:
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator
BinaryOperator<U> combiner);
U减少(U标识,
双功能累加器
二进制运算符组合器);
双功能累加器
可以接受两种不同类型的参数,限制较少,更适合您的情况。一个可能的解决办法是:
<T> Consumer<T> combine(Stream<? extends Consumer<? super T>> consumers) {
return consumers.filter(Objects::nonNull)
.reduce(t -> {}, Consumer::andThen, Consumer::andThen);
}
Consumer combine(Stream如果您有很多消费者,则应用Consumer.and()
将创建一个巨大的消费者包装树,递归处理该包装树以调用每个原始消费者
因此,简单地构建一个消费者列表,并创建一个简单的消费者来对其进行迭代可能更有效:
<T> Consumer<T> combine(Stream<? extends Consumer<? super T>> consumers) {
List<Consumer<? super T>> consumerList = consumers
.filter(Objects::nonNull)
.collect(Collectors.toList());
return t -> consumerList.forEach(c -> c.accept(t));
}
循环版本如何允许返回消费者
?@user7抱歉,但我不理解您的问题。您是否询问当前如何可能(以及原因)。或者如何修复它,使其成为可能?类型转换为(Consumer@user7我现在明白了,但这是不是需要的?为什么你首先要返回消费者
?如果你想返回一个无限制的消费者,你可以简单地用(消费者)
再次强制转换它,这是未选中的,但会起作用。不能c->c.accept(t)
是否替换为Consumer::accept
?@Alexander No,forEach
需要一个Consumer,即接受一个参数但不返回任何内容。Consumer::accept
需要两个参数:Consumer
本身(“this
”)以及要消费的对象。事实上,你可以很容易地注意到它并不等价,因为t
将与该方法引用一起变得不可用。哦,是的,这使得sense@Alexander还要注意的是,forEach
实际上需要一个消费者
<? extends Consumer<? super T>>
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator
BinaryOperator<U> combiner);
<T> Consumer<T> combine(Stream<? extends Consumer<? super T>> consumers) {
return consumers.filter(Objects::nonNull)
.reduce(t -> {}, Consumer::andThen, Consumer::andThen);
}
<T> Consumer<T> combine(Stream<? extends Consumer<? super T>> consumers) {
Consumer<T> identity = t -> {};
BiFunction<Consumer<T>, Consumer<? super T>, Consumer<T>> acc = Consumer::andThen;
BinaryOperator<Consumer<T>> combiner = Consumer::andThen;
return consumers.filter(Objects::nonNull)
.reduce(identity, acc, combiner);
}
Stream<? extends Consumer<? super Foo>> consumers = Stream.of();
combine(consumers);
<T> Consumer<T> combine(Stream<? extends Consumer<? super T>> consumers) {
List<Consumer<? super T>> consumerList = consumers
.filter(Objects::nonNull)
.collect(Collectors.toList());
return t -> consumerList.forEach(c -> c.accept(t));
}
return t -> consumers
.filter(Objects::nonNull)
.forEach(c -> c.accept(t));