7

As this question asked for python, what is the equivalent of Haskell's scanl in Java's streams?

The best I've come up with so far is to use

reduce(identity, accumulator, combiner)

with an accumulator that keeps the latest result and accumulates the results in a list, though the combiner would presumably not be not used. I'm also not sure how to prevent it from being used in parallel, where it would not work.

Perhaps Stream is the wrong interface for (an equivalent of) scanl?

Community
  • 1
  • 1
Graeme Moss
  • 7,995
  • 4
  • 29
  • 42
  • 3
    Yes, `Stream` is not the right interface here. Java's Streams provide only operations which can be efficiently parallelized, which does not include scanl with arbitrary operations. – Louis Wasserman Dec 10 '15 at 21:22

1 Answers1

6

Looks like standard Stream API has no scanl equivalent. One of the reasons is the fact that scanl is strictly left-to-right operation which makes it hard to have benefits from parallel processing (and parallel processing is an important part of Stream API). You may however use third-party libraries like my free StreamEx library. It extends standard Stream API adding many more useful functions including the scanLeft:

List<Integer> list = IntStreamEx.range(10).boxed().scanLeft(Integer::sum);
System.out.println(list);
// outputs [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]

This scanLeft operation is guaranteed to work even with parallel streams, but you're unlikely to have the speedup unless you have some computational intensive upstream operations which could be parallelized.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
  • 4
    I know the OP asked for streams, but if you're working with arrays, you might also consider `Arrays.parallelPrefix`; for instance `Arrays.parallelPrefix(arr, Integer::sum);`. It's not a strict scan left, as I think it needs both an initial value and a binary operator, but well... – Alexis C. Dec 10 '15 at 10:50
  • 3
    @AlexisC., yes, it's a good addition (consider writing your answer!). However it should be noted that `parallelPrefix` needs an associative function like `reduce`. – Tagir Valeev Dec 10 '15 at 11:23