Skip to content
Advertisement

Stream / Reduce a series of functions applied to an input value with bound variables in Java

How does one go about rewriting this loop using a stream.

private final List<RegionSpecificValidator> validators;
public Item applyValidations(Item inbound, Holder holder, Product product) {
    Item toValidate = inbound;
    for (var validator: validators)
        toValidate = validator.validate(toValidate, holder, product);
    return toValidate;
}

It should be possible to rewrite this loop using validators.stream().reduce(...)

I have tried using the guidance here, but I cannot figure out what BiFunction interface needs to be implemented and how.
The interface as it currently stands looks like this:

public interface RegionSpecificValidator {
    Item validate(Item toValidate, Holder holder, Product product);
}

I have looked at this guidance: Reducing a list of UnaryOperators in Java 8
However it’s not clear how I implement andThen in this case, or even if it’s possible.

Advertisement

Answer

You need to use the reduce() method with transformer and combiner.

The three arguments are as follows:

  • inbound is the base case. For example, if validators is an empty list, it is the object that is returned by default
  • (toValidate, validator) -> validator.validate(toValidate, holder, product) it takes an Item and a validator and produces an Item. This happens via the validate() method on the validator.
  • (prev, next) -> next defines how reduction should happen between two items – you need to pick one. In your for-loop you are always overwriting toValidate with the new value, so in this case we should return next, i.e. the last element that we obtained from validator.validate().
public Item applyValidations(Item inbound, Holder holder, Product product) {
    return validators.stream().reduce(
        inbound, 
        (toValidate, validator) -> validator.validate(toValidate, holder, product), 
        (prev, next) -> next
    );
}
Advertisement