当调用 IntBinaryOperator 的新实例时,ApplyAsInt 如何自动工作?

How does ApplyAsInt work automatically when a new instance of IntBinaryOperator is called?

我完成了一个编程练习,然后检查了其他人的答案。我发现了一个我很难理解的问题。

练习是:"Given a string of uppercase letters, for example ABC, return the number of letters missing"

ABC, returns 0
ABD returns 1, because C is missing
BCF returns 3, because A, D and E are missing.

import java.util.function.IntBinaryOperator;

public class TrainInspector {

    static class Op implements IntBinaryOperator {
        int prev = 'A';

        @Override
        public int applyAsInt(int left, int right) {
            left += right - prev - 1;
            prev = right;
            return left;
        }
    }

  public static int countMissingCarriages(String train) {
    if ( train == null || train.isEmpty() ) return 0;
    return train.chars().reduce(1, new Op());
  }

}

我知道 reduce 从给定的参数中为我们提供了一个 int。但是我不明白 applyAsInt 如何在创建新的 IntBinaryOperator 时自动工作。

我已阅读:

http://www.java2s.com/Tutorials/Java/java.util.function/IntBinaryOperator/index.htm

https://www.geeksforgeeks.org/stream-reduce-java-examples/

她就是这样使用applyAsInt()方法

来自abstract class IntPipeline

@Override
public final int reduce(int identity, IntBinaryOperator op) {
    return evaluate(ReduceOps.makeInt(identity, op));
}

来自final class ReduceOps

static TerminalOp<Integer, Integer> makeInt(int identity, IntBinaryOperator operator) {
    class ReducingSink implements ... {
        private int state;

        //...

        @Override
        public void accept(int t) {
            state = operator.applyAsInt(state, t); // <----------
        }

        //...
    }
    return new ReduceOp<Integer, Integer, ReducingSink>(StreamShape.INT_VALUE) {
        @Override
        public ReducingSink makeSink() {
            return new ReducingSink();
        }
    };
}

流码为:

train.chars().reduce(1, new Op())

reduce 的 javadoc 说:

Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. This is equivalent to:

 int result = identity;
 for (int element : this stream)
     result = accumulator.applyAsInt(result, element)
 return result;

要了解如何在此处使用 Op,让我们看一下 等效 非流版本的 countMissingCarriages 方法,方法是应用来自javadoc.

public static int countMissingCarriages(String train) {
    if ( train == null || train.isEmpty() ) return 0;
    
    // values from stream
    char[] stream = train.toCharArray();
    
    // values from 'reduce' parameters
    int identity = 1;
    IntBinaryOperator accumulator = new Op();
    
    // logic from javadoc
    int result = identity;
    for (int element : stream)
        result = accumulator.applyAsInt(result, element);
    return result;
}

希望这有助于澄清事情。