Java Stream.reduce的累加器参数中使用通配符的目的是什么?

Java 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标识, 双功能累加器, 二进制运算符组合器); 有助于根据流中对象的某些属性减少流 但是,我不清楚为什么累加器不能更直接,也不能达到同样的目的: 双功能累加器 累加器的签名中的通配符提供了什么额

Java
流的

<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);