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

标签 java arrays sorting java-stream priority-queue

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

If you need ordered traversal, consider using Arrays.sort(pq.toArray()).

但是,我确实喜欢流式 API,所以我最初拥有的是

Something[] elems = theHeap.stream().sorted(BY_CRITERION.reversed())
                       .toArray(Something[]::new);

(其中 BY_CRITERION 是 PriorityQueue 的自定义比较器,我确实想要它的相反顺序。)与以下相比,使用这个习惯用法有什么缺点吗:

Something[] elems = theHeap.toArray(new Something[0]);
Arrays.sort(elems, BY_CRITERION.reversed());

后一种代码显然更直接地遵循了 API 文档的建议,但除此之外,它是否真的在内存方面更有效率,例如分配的临时结构更少等?

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

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

那么排序效率呢? Arrays.sort() 的文档说

Temporary storage requirements vary from a small constant for nearly sorted input arrays to n/2 object references for randomly ordered input arrays

同时 Stream.sorted() 的文档对这一点保持沉默。因此,至少在可靠记录方面,命令式解决方案似乎具有优势。

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

最佳答案

从根本上说,这两种变体的作用相同,并且由于它们都是库预期用例中的有效解决方案,因此在选择算法或添加优化方面,没有理由认为实现应该优先于另一种。

实际上,这意味着最昂贵的操作(排序)在内部以相同的实现方法结束。 sorted(…) Stream 实现的操作将所有元素缓冲到一个中间数组中,然后调用 Arrays.sort(T[], int, int, Comparator<? super T>) , 它将委托(delegate)给与方法 Arrays.sort(T[], Comparator<? super T>) 相同的方法您在第一个变体中使用,目标是内部 TimSort 中的排序方法类。

所有关于 Arrays.sort 的时间和空间复杂度的讨论适用于 Stream.sort以及。但是虽然有性能差异。对于 Java 10 之前的 OpenJDK 实现,Stream 无法融合 sorted与随后的 toArray步骤,直接使用结果数组进行排序步骤。因此,目前,Stream 变体承担了从用于排序的中间数组到由传递给 toArray 的函数创建的最终数组的最终复制步骤。 .但是 future 的实现可能会学习这个技巧,那么,这两种解决方案之间的相关性能将完全不同。

关于java - 将 PriorityQueue 转换为排序数组的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51079032/

相关文章:

arrays - 和 friend 一起研究C语言动态分配malloc realloc。但是有一个问题。我考虑内存设置

python - Pandas 数据透视表手动对列进行排序

java - 绘图时的 JApplet 加载屏幕

java - 使用 BPEL 调用简单的 WSDL 服务

java - 如何在 HQL 中使用 order by?

java - 如何检查 2D 数组中是否有水平 3 组?

java - Google App Engine 设置替代 Dev 与 Online

javascript - 如何访问多级对象数组?

javascript - 根据最低值更改索引

javascript - 对象中的项目为 'undefined' 的问题