4

I'm trying to understand the behavior of parallelStream() in java 8. Here is my sample code.

List<Person> javaProgrammers = new ArrayList<Person>() {
    {
        add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 43, 2000));
        add(new Person("Tamsen", "Brittany", "Java programmer", "female", 33, 1500));
        add(new Person("Floyd", "Donny", "Java programmer", "male", 33, 1800));
        add(new Person("Sindy", "Jonie", "Java programmer", "female", 32, 1600));
        add(new Person("Vere", "Hervey", "Java programmer", "male", 22, 1200));
        add(new Person("Maude", "Jaimie", "Java programmer", "female", 33, 1900));
        add(new Person("Shawn", "Randall", "Java programmer", "male", 33, 2300));
        add(new Person("Jayden", "Corrina", "Java programmer", "female", 33, 1700));
        add(new Person("Palmer", "Dene", "Java programmer", "male", 33, 2000));
        add(new Person("Addison", "Pam", "Java programmer", "female", 34, 1300));
    }
};

System.out.println("Serial:" + javaProgrammers.stream().filter(person -> person.age == 33).findFirst().toString());
System.out.println("Parallel:" + javaProgrammers.parallelStream().filter(person -> person.age == 33).findFirst().toString());

Here I'm comparing stream() and parallelStream(), and I expect Brittany Tamsen to be return always in stream() call because that's the first match. But for parallelStream() I do not expect Brittany Tamsen to be returned always because it can be one of any matches, as I expect it to run in parallel.

But the problem is that it also returns Brittany Tamsen always. So it doesn't look like it runs in parallel.

Am I missing something here?

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
Bee
  • 12,251
  • 11
  • 46
  • 73
  • 3
    note that the double bracket initialization pattern is discouraged, as it creates additional classes. – the8472 Nov 14 '16 at 07:32
  • My IDE (idea) doesn't complain, though. What is the recommended way? What do you mean by additional classes? – Bee Nov 14 '16 at 07:35
  • Found the answer here. https://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/ Thanks – Bee Nov 14 '16 at 07:37
  • 2
    That's a bad heuristic. Just because your IDE doesn't complain about it doesn't mean it's efficient. It's not smarter than you after all. – the8472 Nov 14 '16 at 07:39
  • 1
    And it’s not even shorter than the straight forward solutions, e.g. if you don’t need a resizeable list, use `List javaProgrammers = Arrays.asList( new Person(…), new Person(…), … );`, it’s shorter *and* more efficient. If you really need a resizable `ArrayList`, you may just pass that list to the `ArrayList`’s constructor or construct an intially empty `ArrayList` and use `Collections.addAll`, in either case, you’re making a small trade-off between brevity and efficiency, but it’s still better than the double curly brace subclassing (and potentially memory leak creation). – Holger Nov 14 '16 at 10:38
  • 4
    Regarding the actual question, [this](http://stackoverflow.com/a/29218074/2711488) might help. – Holger Nov 14 '16 at 10:40

2 Answers2

5

In addition to Bohemian's answer, It's important to add that, yes, findFirst() will return the first element matching the predicate, whether the stream is parallel or not, since the stream has an encounter order in this case (being created from a List).

findAny(), on the contrary, is free to return any element matching the predicate (and should thus be preferred if you don't really care about which matching element is returned, since it might allow returning sooner in case of a parallel stream).

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
5

There is a whole paragraph on ordering in the package documentation and another one the interaction between concurrency and ordering further down.

Excerpt (reading the rest is highly recommended):

Streams may or may not have a defined encounter order. Whether or not a stream has an encounter order depends on the source and the intermediate operations. Certain stream sources (such as List or arrays) are intrinsically ordered

The findFirst documentation itself then refers to the encounter order concept defined above.

Returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty. If the stream has no encounter order, then any element may be returned.

The Spliterator and Collector docs also describe some behavior relevant to ordering for more complex uses of parallel streams.

the8472
  • 40,999
  • 5
  • 70
  • 122