问题是关于java.util.stream.Stream.reduce(U identity,BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)方法。
要求之一是组合器功能必须与累加器功能兼容。对于所有u和t,必须满足以下条件:
combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t) (*)
Run Code Online (Sandbox Code Playgroud)
如果combiner和accumulator相同,则上述相等性自动成立。
我的问题
有没有使用combiner和和减少流的示例accumulator?
更新
为了澄清一些事情:
BinaryOperator实际上是在扩展BiFunction,因此在需要BiFunction时可以使用它。如果U和T相同,则始终是合法的:
operator<T> op = (x,y) -> something;
stream.reduce(id, op, op);
Run Code Online (Sandbox Code Playgroud)
我从来没有说过我可以一直使用combineras,acumulator因为在一般情况下,它们用于不同的目的并且是不同的Java类型。
另外,我对平凡的示例不感兴趣,但对并行流进行归约时在实践中遇到的自然示例不感兴趣。
对于一些琐碎的示例,有很多教程,例如本教程
我为什么要问这个问题
基本上,存在这种简化方法的原因是针对并行流。在我看来,条件(*)如此之强,以至于在实践中,由于很少有还原操作可以实现此还原,因此它使还原无效。
所以,这里有几个例子。其中一些可能被认为是“微不足道的”,特别是当已经有一个函数可以为您做这件事的时候。
T和U相同的示例这些很难想出,而且有点做作,因为它们通常涉及假设流的元素和正在累积的对象具有不同的含义,即使它们具有相同的类型。
如果我们有一个整数流,我们可以使用以下方法对它们进行计数reduce:
stream.reduce(0, (count, item) -> count+1, (a, b) -> a+b);
Run Code Online (Sandbox Code Playgroud)
显然,我们可以stream.count()在这里使用,但我愿意打赌内部count使用 3 个参数版本reduce。
T和U不同的示例这给了我们很大的自由度,显然,累加器和组合器在这里永远不会相同,因为它们有不同的类型。
我们可能想要聚合的最常见方法之一是收集到一个集合中。我们可以使用reduce它,但由于在 Java 中集合类型通常是可变的,因此使用collect通常会更有效。此规则通常适用:如果结果类型可变,请使用collect而不是reduce。
class Range {
static Range NONE = new Range(Double.NaN, Double.NaN);
final double min, max;
static Range of(double min, double max) {
if(Double.isNaN(min) || Double.isNaN(max) || min>max) {
throw new IllegalArgumentException();
}
return new Range(min, max);
}
private Range(double min, double max) {
this.min = min;
this.max = max;
}
boolean contains(double value) {
return this!=Range.NONE && min<=value && max>=value;
}
boolean spans(Range other) {
return this==other
|| other==Range.NONE
|| (contains(other.min) && contains(other.max));
}
}
Range range = streamOfDoubles.reduce(
Range.NONE,
(range, value) -> {
if(range==Range.NONE)
return Range.of(value, value);
else if(range.contains(value))
return range;
else
return Range.of(Math.min(value, range.min), Math.max(value, range.max));
},
(a, b) -> {
if(b.spans(a))
return b;
else if(a.spans(b))
return a;
else
return Range.of(Math.min(a.min, b.min), Math.max(a.max, b.max));
}
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
128 次 |
| 最近记录: |