10

I have the following code:

Set<Integer> l = new TreeSet<>();
l.add(1);
l.add(10);
l.add(3);
l.add(-3);
l.add(-4);

and I want to unorder the collection with:

l.stream().unordered().forEach(System.out::println);

but the forEach returns always the collection ordered!

Then I have also another doubt about the below sentence from here:

For sequential streams, the presence or absence of an encounter order does not affect performance, only determinism. If a stream is ordered, repeated execution of identical stream pipelines on an identical source will produce an identical result; if it is not ordered, repeated execution might produce different results.

In fact if I try this code on an unordered stream the results is always the same and never produce different results:

Arrays.stream( new int[]{8, -1, 3}).forEach(System.out::println);
Arrays.stream( new int[]{8, -1, 3}).forEach(System.out::println);

I really don't understand this API part...

2 Answers 2

20

The unordered() operation doesn't do any actions to explicitly unorder the stream. What it does is that it removes the constraint on the stream that it must remain ordered, thereby allowing subsequent operations to use optimizations that don't have to take ordering into consideration.

You can read about this in the Java 8 docs:

For sequential streams, the presence or absence of an encounter order does not affect performance, only determinism. If a stream is ordered, repeated execution of identical stream pipelines on an identical source will produce an identical result; if it is not ordered, repeated execution might produce different results.
For parallel streams, relaxing the ordering constraint can sometimes enable more efficient execution.

...

In cases where the stream has an encounter order, but the user does not particularly care about that encounter order, explicitly de-ordering the stream with unordered() may improve parallel performance for some stateful or terminal operations.

3
  • Yes but in the doc is written: """Some intermediate operations, such as sorted(), may impose an encounter order on an otherwise unordered stream, and others may render an ordered stream unordered, such as BaseStream.unordered()""" In fact if I call sorted on a unsorted collection it sorts...
    – xdevel2000
    Jan 25, 2014 at 12:04
  • 1
    Sure, but a sorted stream is still valid to pass on as an unordered stream, it just doesn't leave any guarantees about it.
    – Keppil
    Jan 25, 2014 at 12:09
  • so to remove ordering constraints we use unorderd() and foreach() methods ? if so why we have 2 methods to do the same thing ?and it doesn't even mean anything when you are working on serial stream Aug 24, 2018 at 6:01
14

You are using a TreeSet, which orders the elements. So, the elements will be:

-4, -3, 1, 3, 10

Using a serial stream does not change the order, so the result is not dependent on the property of the stream of being ordered/unordered, as you can see in the first example "Serial Stream" (and as you noticed yourself).

l.stream().map(s->s+" ").forEach(System.out::print);

Result: -4 -3 1 3 10

l.stream().unordered().map(s->s+" ").forEach(System.out::print);

Result: -4 -3 1 3 10

If you make the stream parallel, then more than one thread can be created and the result is no longer guaranteed, because it depends on the specific execution. Note also that forEach() is not an ordered operation, meaning that it executes whenever it has something to process in its pipeline. See the example "Unordered Operations on a Parallel Stream":

l.stream().parallel().map(s->s+" ").forEach(System.out::print);

Result: 3 10 -3 1 -4

l.stream().unordered().map(s->s+" ").parallel().forEach(System.out::print);

Result: 3 -4 -3 1 10

Things change when you use Ordered Operations (like findFirst(), limit() and skip()) in a parallel stream. When you use findFirst() in a pipeline, what you really want is having the first element, according to the order of the elements in the stream, you just don't want any element, in which case you would be using findAny(). To have deterministic results by these operations, you lose the benefits of using a parallel stream, because the execution has to be serialized to process the elements in a specific order.

   l.stream().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);

Result: 1 . This result will always be the same, no matter how many times you execute the code.

l.stream().unordered().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);

Result: -3 . This result may (or may not) change every time you execute the code, because we specified that the order is not important.

Here is the complete code:

public static void main(String[] args) {
    Set<Integer> l = new TreeSet<>();
    l.add(1);
    l.add(10);
    l.add(3);
    l.add(-3);
    l.add(-4);

    System.out.println("Serial Stream");
    l.stream().map(s->s+" ").forEach(System.out::print);
    System.out.println();
    l.stream().unordered().map(s->s+" ").forEach(System.out::print);
    System.out.println("\n");

    System.out.println("Unordered Operations on a Parallel Stream");
    l.stream().parallel().map(s->s+" ").forEach(System.out::print);
    System.out.println();
    l.stream().unordered().map(s->s+" ").parallel().forEach(System.out::print);
    System.out.println("\n");

    System.out.println("Ordered Operations on a Parallel Stream");
    l.stream().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);
    System.out.println();
    l.stream().unordered().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);
    System.out.println("\n");

}

Serial Stream

-4 -3 1 3 10

-4 -3 1 3 10

Unordered Operations on a Parallel Stream

3 10 -3 -4 1

-3 1 3 10 -4

Ordered Operations on a Parallel Stream

1

-3

1
  • 1
    so there is no way to see different result everytime you run the code , when you are working with serial stream ? Aug 24, 2018 at 6:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.