Java 8中的parallelStream()是否保证顺序?

4

我正在尝试理解Java 8中parallelStream()的行为。这是我的示例代码。

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());

这里我在比较 stream()parallelStream(),我期望在 stream() 调用中总是返回 Brittany Tamsen,因为这是第一个匹配项。但对于 parallelStream(),我并不期望总是返回 Brittany Tamsen,因为它可以是任何匹配项之一,我期望它并行运行。
但问题在于它也总是返回 Brittany Tamsen。所以看起来它并没有并行运行。
我错过了什么吗?

3
请注意,双括号初始化模式不被推荐使用,因为它会创建额外的类。 - the8472
我的IDE(idea)没有抱怨,但是什么是推荐的方法?你所说的附加类是什么意思? - Bee
在这里找到了答案。https://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/ 谢谢。 - Bee
2
那是一个糟糕的启发式方法。仅仅因为你的IDE没有抱怨它并不意味着它是高效的。毕竟,它并不比你更聪明。 - the8472
1
而且它甚至不比直接的解决方案更短,例如,如果您不需要可调整大小的列表,则使用List <Person> javaProgrammers = Arrays.asList(new Person(...),new Person(...),...);,它更短且更高效。如果您真的需要一个可调整大小的 ArrayList,则可以将该列表传递给 ArrayList 的构造函数或构造一个最初为空的 ArrayList 并使用 Collections.addAll,在任何情况下,您都需要在简洁性和效率之间做出一些小的权衡,但这仍然比双花括号子类化(可能会导致内存泄漏)更好。 - Holger
4
关于实际问题,这里可能会有所帮助。 - Holger
2个回答

5
除了Bohemian的回答外,还要补充说明:findFirst() 返回匹配谓词的第一个元素,无论流是否并行。在这种情况下(从List创建),流具有遭遇顺序。
相反地,findAny() 则可以返回与谓词匹配的任何元素(因此,如果您不关心返回哪个匹配元素,则应优先考虑它,因为在并行流的情况下,它可能会更快地返回)。

5
包文档中有一个关于排序的整段内容, 后面还有另一段关于并发和排序交互的内容。流可能有也可能没有定义好的相遇顺序,这取决于源和中间操作。某些流源(例如List或数组)是本质有序的。然后,findFirst文档参考了上面定义的相遇顺序概念。返回描述此流的第一个元素的Optional,如果流为空,则返回空的Optional。如果流没有相遇顺序,则可以返回任何元素。 SpliteratorCollector文档还描述了一些与排序相关的行为,适用于更复杂的并行流使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接