我一直对Collections.parallelStream()
和Collections.stream().parallel()
之间的区别很好奇。根据Javadocs,parallelStream()
试图返回并行流,而stream().parallel()
返回并行流。通过自己的一些测试,我没有发现任何不同之处。这两种方法的区别在哪里?一个实现比另一个更时间高效吗?谢谢。
我一直对Collections.parallelStream()
和Collections.stream().parallel()
之间的区别很好奇。根据Javadocs,parallelStream()
试图返回并行流,而stream().parallel()
返回并行流。通过自己的一些测试,我没有发现任何不同之处。这两种方法的区别在哪里?一个实现比另一个更时间高效吗?谢谢。
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
作为默认方法,它可以在实现中被覆盖 (这就是 Collections
内部类实际所做的)。
这暗示着即使默认方法返回一个并行流,也可能有集合覆盖此方法以返回一个非并行流。这可能是文档的原因。
同时,即使 parallelStream
返回一个串行流,它仍然是一个 Stream
,你可以轻松地在其上调用 parallel
:
Collections.some()
.parallelStream() // actually sequential
.parallel() // force it to be parallel
至少对我来说,这看起来很奇怪。
似乎文档应该以某种方式说明,在调用parallelStream
之后,没有必要再次调用parallel
来强制执行并行处理 - 因为这可能是无用的甚至对处理有害。
编辑
对于阅读此内容的任何人 - 请阅读Holger的评论;它涵盖了我在此答案中未提到的情况。
Stream
API实现,但那时,当调用.parallel()
时,它完全控制发生的事情... - HolgerisParallel()
返回true
也没有问题。同样地,如果一个单例集合上的流没有flatMap
操作,它将永远不会使用第二个线程,但是,让isParallel()
返回true
也没有问题。这也适用于所有底层分裂器在trySplit
中返回null
的流;如果没有像sorted
或flatMap
这样的操作,调用.parallel()
也不重要,它不会产生任何影响。 - HolgerthatSource.parallelStream().sorted().otherOps()
,一旦内部使用的数组已经被填充,因为此时处理完全与源分离。我有一种感觉,这个句子源于源和流实现之间的交互仍在进行的时期。 - Holgersorted
操作,它会将元素从Spliterator
复制到Sink
(数组或ArrayList
)中,对吗?很抱歉这么晚才提出这个问题。 - Eugenesorted()
使用的临时存储(无论是数组还是其他)与源集合无关,因此可以并行处理,即使源集合试图否认它。同样,如果分裂器的 trySplit
方法返回 null
,则流实现可能会转向缓冲策略,就像 AbstractSpliterator.trySplit
所做的那样。实际上,如果流这样做而不是 AbstractSpliterator
更有意义... - HolgerCollections.parallelStream()
和Collections.stream().parallel()
没有区别。它们都会根据底层分割器的限制来分割流,并且它们都将使用默认的ForkJoinPool
(除非已经在另一个池内运行)。
class Employee {
String name;
int salary;
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
}
class ParallelStream {
public static void main(String[] args) {
long t1, t2;
List<Employee> eList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
eList.add(new Employee("A", 20000));
eList.add(new Employee("B", 3000));
eList.add(new Employee("C", 15002));
eList.add(new Employee("D", 7856));
eList.add(new Employee("E", 200));
eList.add(new Employee("F", 50000));
}
/***** Here We Are Creating A 'Sequential Stream' & Displaying The Result *****/
t1 = System.currentTimeMillis();
System.out.println("Sequential Stream Count?= " + eList.stream().filter(e -> e.getSalary() > 15000).count());
t2 = System.currentTimeMillis();
System.out.println("Sequential Stream Time Taken?= " + (t2 - t1) + "\n");
/***** Here We Are Creating A 'Parallel Stream' & Displaying The Result *****/
t1 = System.currentTimeMillis();
System.out.println("Parallel Stream Count?= " + eList.parallelStream().filter(e -> e.getSalary() > 15000).count());
t2 = System.currentTimeMillis();
System.out.println("Parallel Stream Time Taken?= " + (t2 - t1));
/***** Here We Are Creating A 'Parallel Stream with Collection.stream.parallel' & Displaying The Result *****/
t1 = System.currentTimeMillis();
System.out.println("stream().parallel() Count?= " + eList.stream().parallel().filter(e -> e.getSalary() > 15000).count());
t2 = System.currentTimeMillis();
System.out.println("stream().parallel() Time Taken?= " + (t2 - t1));
}
}
.stream()、.parallelStream() 和 .stream().parallel()
,使用相同数量的记录,并且能够确定这三种方法所花费的时间。以下是我提到的输出结果。Sequential Stream Count?= 300
Sequential Stream Time Taken?= 18
Parallel Stream Count?= 300
Parallel Stream Time Taken?= 6
stream().parallel() Count?= 300
stream().parallel() Time Taken?= 1
我不确定,但是如上所述,stream().parallel()
的执行时间是parallelStream()
的六分之一。
如果有专家建议,仍然非常欢迎。
Sequential Stream Count?= 15000000
Sequential Stream Time Taken?= 102
Parallel Stream Count?= 15000000
Parallel Stream Time Taken?= 64
stream().parallel() Count?= 15000000
stream().parallel() Time Taken?= 97
- Ali Sadeghi