unordered()

Joe Bowbeer joe.bowbeer at gmail.com
Mon Dec 24 17:01:51 PST 2012


Continuing with Uncle Bob's FP snippet:

    (take 25 (squares-of (integers)))

I can code this in jdk8lambda-b69 as:

    Function<Integer, Integer> square = (Integer i) -> i * i;
    Stream<Integer> is = Streams.iterate(0, i -> i +
1).map(square).limit(25);


First, *note* that the following simplification won't compile because the
RHS creates an IntStream:

    Stream<Integer> is = Streams.iterate(0, i -> i + 1).map((Integer i) ->
i * i).limit(25);

This is a bug, right?


Now something about unordered()..

When I add parallel() before the map() and print the result, I find that
the into() form creates ordered results no matter where I insert
unordered() in the pipeline, whereas forEach() already produces unordered
results.

1. Always ordered, regardless of unordered()

    out.print(is.map(Object::toString).into(new StringJoiner(" ")));

    => 0 1 4 9 ... 441 484 529 576

2. Naturally unordered

    is.forEach(i -> out.print(i + " "));

    => 0 529 576 441 ... 9 16 1 4

Seems weird.

-Joe



On Fri, Dec 21, 2012 at 2:13 PM, Brian Goetz <brian.goetz at oracle.com> wrote:

> So, the move to a more explicit choice of merging or concurrent tabulation
> also reduces (heh) the need for unordered(), though it does not eliminate
> it completely.  (Limit, cancelation, and duplicate removal all have
> optimized versions if encounter order is not significant.)
>
> Kevin pointed out that .unordered() is pretty easy to miss, and people
> will not know that they don't know about it.  One possible is to make it
> more explicit at one end of the pipeline or the other (the only operation
> that is order-injecting is sorted(), and presumably if you are sorting you
> really care about encounter order for the downstream ops, otherwise the
> sort was a waste of time.)
>
> The proposed tabulator / reducer stuff makes the order-sensitivity clear
> at the tail end, which is a good place to put it -- the user should know
> whether a reduce or a forEach is what they want -- if not the user, who?
>  (Only the user knows whether he cares about order or not, and knows
> whether his combination functions are commutative or not.)  The other
> less-ignorable place to put an ordering opt-out is at the head; we could
> make things more clear with adding
>
>   .parallelUnorderedStream()
> alongside
>   .stream()
> and
>   .parallelStream()
>
> The obvious implementation of parallelUnorderdStream is:
>
>     default Stream<E> parallelStream() {
>         return stream().unordered();
>     }
>
> which is also the most efficient place to put the .unordered (at the head.)
>
>
>


More information about the lambda-libs-spec-observers mailing list