【问题标题】:Java: Collection.sort() vs Sorted Set vs PriorityQueue [duplicate]Java:Collection.sort() vs Sorted Set vs PriorityQueue [重复]
【发布时间】:2025-12-03 22:30:01
【问题描述】:

我有以下结构:MyObject 列表列表, 和比较 2 MyObjects 的比较器

任务是从列表中获取最多 N 个较小的对象。

这个问题可以通过几种方式解决:

  1. 将所有元素放在一个新列表中并使用 Collections.sort() 或 Arrays.parallelSort()

  2. 将所有元素放入ProirityQueue,然后取出N个top元素

  3. 将所有元素放入 SortedSet (TreeSet) 并检索需要的元素 使用迭代器

我不知道如何选择。标准是性能。 “内部”列表的大小约为 20 个元素,“外部”列表的大小约为 10

【问题讨论】:

  • 那么,除了写这个问题之外,您到目前为止还做过什么吗?您是否查看过每种可能解决方案的数据结构上的任何操作的时间复杂度?
  • “N 个较小的对象”是什么意思?您需要 N 个比一个特定对象更小的对象,还是需要整个构造中的 N 个最小对象?
  • 对于大小列表 2010,这与性能无关,但如果您的元素不是唯一的,则不能使用 SortedSet
  • 即使“标准是性能”,更改列表的频率与访问缩减列表的频率也很重要。怀疑你是否能绕过分析你的选择。
  • 如果只需要部分排序,那就只有N元素。那么最好的可能是PriorityQueue,它正是为此目的而构建的。将所有内容放入其中,然后调用NpullMin 方法(或调用方式)。如果你仔细看看内部是如何实现的,你会立即明白为什么PriorityQueue 是这个任务的好选择。但是,正如其他人所说,对于仅包含 20 元素的列表,情况可能会有所不同。对于像 1mio 这样更大的列表,您会注意到性能差异很大。

标签: java performance sorting


【解决方案1】:

如果您只想要大约 200 个中最低的 N 个元素,并且 N 很小(例如 10-20),那么您为什么还要费心将所有元素添加到另一个结构(无论是列表还是 PriorityQueue)?只需创建一个包含 N 个项目的数组(或列表,如果必须的话)。遍历列表列表中的每个元素,并将该元素插入到 N 数组中的正确排名中。丢弃从列表底部删除的第 N 个元素。这类似于插入排序算法,但只进行部分排序。

如果 N 很大(比如总共 200 个项目中的 150 个),那么完整排序或 PriorityQueue 可能会更好。您需要测量。

【讨论】:

  • 谢谢!我将立即实施和测试。
  • 我测试了您提出的解决方案,结果非常好。比较操作的数量急剧减少(我在日志中看到了这一点)。结果是:使用并行排序 - 10000 次迭代约 18 毫秒,使用优先队列:约 60 毫秒,使用“部分排序”:10000 次约 7 毫秒。谢谢!