Java 将PriorityQueue转换为排序数组的最佳方法

Java 将PriorityQueue转换为排序数组的最佳方法,java,arrays,sorting,java-stream,priority-queue,Java,Arrays,Sorting,Java Stream,Priority Queue,我关注从包含数千个元素的Java PriorityQueue创建排序数组的不同风格。说 如果需要有序遍历,请考虑使用数组。排序(pq.toAlayle())。 然而,我确实喜欢流式API,所以我最初拥有的是 Something[] elems = theHeap.stream().sorted(BY_CRITERION.reversed()) .toArray(Something[]::new); (其中,BY_criteria是PriorityQ

我关注从包含数千个元素的Java PriorityQueue创建排序数组的不同风格。说

如果需要有序遍历,请考虑使用数组。排序(pq.toAlayle())。 然而,我确实喜欢流式API,所以我最初拥有的是

Something[] elems = theHeap.stream().sorted(BY_CRITERION.reversed())
                       .toArray(Something[]::new);
(其中,
BY_criteria
是PriorityQueue的自定义比较器,我确实希望使用与之相反的顺序。)与以下情况相比,使用此习惯用法是否有任何缺点:

Something[] elems = theHeap.toArray(new Something[0]);
Arrays.sort(elems, BY_CRITERION.reversed());
后一段代码显然更直接地遵循了API文档的建议,但除此之外,它在内存方面是否真的更有效,例如分配的临时结构更少等等

我认为流解决方案必须在临时结构(数组?)中缓冲流元素,然后对它们进行排序,最后将排序后的元素复制到
toArray()
中分配的数组中

而命令式解决方案将在新分配的数组中缓冲堆元素,然后对它们进行排序。因此,这可能会减少一个复制操作。(还有一个数组分配。
Collection.toArray(新的T[size])
Collection.toArray(新的T[0])
的讨论在这里是切向相关的。例如,请参阅为什么在OpenJDK上后者更快。)

那么分拣效率呢?医生说

临时存储要求从几乎排序的输入数组的小常量到随机排序的输入数组的n/2对象引用

Stream.sorted()
的文档对此没有说明。因此,至少就可靠的文档记录而言,强制解决方案似乎具有优势


但是还有什么需要知道的吗?

从根本上说,两种变体都是相同的,因为它们都是库的预期用例中的有效解决方案,所以在选择算法或添加优化方面,实现没有理由会选择一种而不是另一种


在实践中,这意味着最昂贵的操作,排序,在内部以相同的实现方法结束。流实现的
sorted(…)
操作将所有元素缓冲到一个中间数组中,然后调用
数组。sort(T[],int,int,comparator)不使用流几乎总是性能更好的选择(除非使用
.parallel()
和数以百万条目的hava数据)如果优先级队列已按排序顺序为您提供元素,为什么要再次排序。请使用
按\u标准初始化优先级队列。反转()comparator@SleimanJneidi因为它不是。只有peek()和poll()尊重比较器。没有用于有序遍历的方法。这在文档中有规定。@Sebastian关于流的要点是,它们表示它们做什么,而不是它们如何做。在内部,它们使用很多对象,在这里和那里创建新的引用。这看起来很不错。但就性能而言,它至少不像serial所说的那样最好的选择。而使用数组方法只创建一个数组,然后对其进行排序。不再对其执行任何操作。这就是为什么它更快的原因