2

I have the following for each loop:

int someOtherVal = 0;
List<Applicators> applicatorList = List.of(applicator1, applicator2);
MyClass result = initialClassValue;

for(Applicator applicator: applicatorList) {
    result = applicator.apply(result, someOtherVal);
}

The closest I can get to it using Stream API is:

applicatorList.stream()
    .reduce(
         initialClassValue,
         (intermediateResult, applicator) -> applicator.apply(intermediateResult, someOtherVal),
         (intermediateResult1, intermediateResult2) -> intermediateResult1 // complete garbage but need to provide for parallel streams which I am not using
    )

Is there some other way to implement this which does not involve the needless overriding of combiner function?

My beef with using combiner function is that -

  1. I am not using parallel streams, so combining of intermediate results should not be required
  2. the garbage combiner override actually doesn't make sense in this context
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • No. I would suggest that you just stick with the for loop, or write your own `fold` helper method (that uses a for loop). See https://stackoverflow.com/questions/41240414/equivalent-of-scalas-foldleft-in-java-8 – Sweeper Apr 19 '22 at 18:32
  • 1
    What’s wrong with the loop? Even if you omit the combiner function, the Stream operation is not simpler (or better in any form). – Holger Apr 21 '22 at 09:18

1 Answers1

2

You can do it by not specifying the initial value in the reduce method. However, this too has its disadvantages. Here is a related example:

  • create my own sum lambda (could have used Integer::sum)
  • it returns an Optional<T> of some type T.
  • due to the lack of an initial value it returns the first via orElse. But then, that is what your method would do if only one value. Or you could just return the optional and check if a value was present.
BinaryOperator<Integer> sumThem = (a,b)->a + b;
int[] arr = {1,2,3,4,5,6,7};

int sum = Arrays.stream(arr).boxed().reduce(sumThem::apply).orElse(1);

But there is nothing wrong with using a loop and may be the best way to go.

WJS
  • 36,363
  • 4
  • 24
  • 39