Как ApplyAsInt работает автоматически, когда вызывается новый экземпляр IntBinaryOperator? - PullRequest
1 голос
/ 20 октября 2019

Я выполнил упражнение по программированию, а затем проверил ответы других людей. Я нашел тот, который мне трудно понять.

Упражнение: «Если задана строка из заглавных букв, например, ABC, вернуть количество пропущенных букв» *

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

}

Я понимаю, что сокращение дает нам int из заданных параметров. Однако я не понимаю, как applyAsInt работает автоматически при создании нового IntBinaryOperator.

Я прочитал:

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

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

Ответы [ 2 ]

3 голосов
/ 20 октября 2019

Она использует метод 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();
        }
    };
}
2 голосов
/ 20 октября 2019

Код потока:

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

Javadoc reduce говорит:

Выполняет сокращение элементов этого потока,используя предоставленное значение идентичности и ассоциативную функцию накопления, и возвращает уменьшенное значение. Это эквивалентно:

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

Надеюсь, это поможет прояснить ситуацию.

...