Java Stream.reduce的累加器参数中使用通配符的目的是什么?
JavaJava Stream.reduce的累加器参数中使用通配符的目的是什么?,java,generics,java-8,Java,Generics,Java 8,Java流的 <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner); U减少(U标识, 双功能累加器, 二进制运算符组合器); 有助于根据流中对象的某些属性减少流 但是,我不清楚为什么累加器不能更直接,也不能达到同样的目的: 双功能累加器 累加器的签名中的通配符提供了什么额
流的
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
U减少(U标识,
双功能累加器,
二进制运算符组合器);
有助于根据流中对象的某些属性减少流
但是,我不清楚为什么累加器
不能更直接,也不能达到同样的目的:
双功能累加器
累加器的签名中的通配符提供了什么额外的灵活性(以降低可读性为代价)
为什么蓄能器不能更直接,并达到相同的目的:
可能是这样,但这将比需要的限制更大。如果你有话要说
BiFunction<String, Object, String> accumulator = (a,b) -> a + b;
或
i、 e.您可以为这两种缩减编写一个累加器。它允许使用函数或lambda,其中第二个参数类型不需要是流的确切类型,但可以是其任何超类型。这允许:
- 创建可用于不同类型流的累加器
- 将接受超类型
T
的现有方法用作累加器
例如,您可以使用流
累加器来接受数字
,或者流
累加器接受字符序列
,甚至对象
更重要的是,这遵循了常见的JDKAPI风格:在每个签名中,如果可以使用更窄或更宽的类型,就应该使用它。我从未见过这个规则被记录在案,但我不知道JDK中有任何例外
请参阅以获得更好的解释
例如,用于计算任何流的不同项的累加器可能如下所示:
public class DistinctCounter {
Set<Object> set = new HashSet<>();
// count() accepts object of any type
public int count(int prev, Object item) {
return prev + set.add(item) ? 1 : 0;
}
}
公共类DistinctCounter{
Set=newhashset();
//count()接受任何类型的对象
公共整数计数(整数上一个,对象项){
返回上一个+设置添加(项目)?1:0;
}
}
并可用于流
,如下所示:
Stream<String> stream = ...
final DistinctCounter c = new DistinctCounter();
int count = stream.reduce(0, c::count, Integer::add);
Stream=。。。
最终DistinctCounter c=新DistinctCounter();
int count=stream.reduce(0,c::count,Integer::add);
虽然这个例子不太实用,但希望它能帮助理解 基本上-一个流
可以被一些双功能
使用。谢谢!这个例子有点做作:System.out.println(Stream.of(1,-2,3).reduce(“long num:”,acculator,(a,b)->a+b))代码>产生long num:1-23
——不确定这有多有用。此外,它似乎也能起作用,因为Java使用字符串操作数处理+
时会产生副作用。你真的会在实践中使用这样的函数吗?@KedarMhaswade很难说,但从API设计师的角度来看,几乎可以肯定的是,有一天会有人问,如果限制在
Imo,我为什么不能这样做呢?这更多的是因为一些指导原则:如果签名中可以使用更窄(或更宽)的类型,这些例子违反了API协议,因为非空字符串不是字符串连接的标识值。这就是为什么当你用平行流尝试时,它们会产生无意义的结果。@Holger我相信,正如我所写的,第二个例子之所以有效,是因为。另一点是,由于这种使用没有令人信服的案例,如果这个API是从BiFunction
开始的,那么将来的版本是否可以在需要时使它BiFunction
而不破坏兼容性(或者增强其使用)?
public class DistinctCounter {
Set<Object> set = new HashSet<>();
// count() accepts object of any type
public int count(int prev, Object item) {
return prev + set.add(item) ? 1 : 0;
}
}
Stream<String> stream = ...
final DistinctCounter c = new DistinctCounter();
int count = stream.reduce(0, c::count, Integer::add);