Java Collectors.reducing 实施

Java Collectors.reducing implementation

int val = integerList.stream().collect(
        Collectors.reducing(0, a1 -> a1 * 5, (a1, a2) -> a1 + a2));

以上代码将 operation.Transforming 整数流和聚合函数缩减为 return Integer 。 我无法理解下面的代码和减少的内部实现 operation.How Java 可以执行下面的状态函数?谢谢!

java.util.stream.Collectors:reducing method
    public static <T, U>
    Collector<T, ?, U> reducing(U identity,
                                Function<? super T, ? extends U> mapper,
                                BinaryOperator<U> op) {
        return new CollectorImpl<>(
                boxSupplier(identity),
                (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
                (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
                a -> a[0], CH_NOID);
    }

也许吧,我会更好地澄清我的问题。上面的实现是如何获取数据流的。 a[0],b[0] 是指数据流吗?我相信以上是为供应商和累加器提供功能实现。我想通过代码了解缩减过程是如何工作的。

该函数接受三个参数:

  • 第一个是身份。减少一个流时,你必须从某个地方开始(否则,减少一个空列表的结果会是什么?)。身份是应用于链中第一个归约操作的第一个参数的对象

  • 第二个是映射器。 reducing() 是一种广义操作 - 您可以将类型 T 的流的元素缩减为类型 U 的最终结果,因此您必须提供提供类型 [=] 的中间操作14=] 元素来自类型 T 元素。如果T == U并且你不想转换,你可以在这里提供一个身份函数

  • 第三个参数是缩减函数 - 这是按顺序应用于流元素的函数,从 identity

    开始

因此,举个例子:

如果您只想将 Integer 流的元素汇总为一个整数,您可以使用 Collectors.reducing(0, x -> x, (x, y) -> x + y).

如果要汇总 String 流中 String 的长度,可以使用 Collectors.reducing(0, String::length, (x, y) -> x + y).

如果你想从一串Double中得到最大值Double,但不小于Math.PI,你可以使用Collectors.reducing(Math.PI, x -> x, Math::max).

此外,如果您希望缩减是有状态的,请记住您可以将对对象内部方法的引用用作缩减器。这样,对象就可以用来保持状态。例如,这里有一个 "taxing reductor",每增加 100 次,它的分数就会增加 1 "tax":

public class Taxer implements BinaryOperator<Integer> {
 int counter = 0;

 @Override
 public Integer apply(Integer i1, Integer i2) {
  counter++;
  if (counter % 100 == 0) {
   return i1 + i2 + 1;
  } else {
   return i1 + i2;
  }
 }
}

...

Taxer t = new Taxer();

...

.collect(Collectors.reducing(0, x -> x, t);

同样可以扩展使用来实现复杂的情况,例如 groupingBy

Map<String, Integer> output = Stream.of("this", "word", "is", "the", "best")
    .collect(Collectors.groupingBy(x-> x.substring(0, 1),
            Collectors.reducing(0, x-> x.length(), (x, y)-> x + y)));

这里首先将输入字符串根据其开头的字符分组,然后将长度相加