哪个实现不那么“重”:PriorityQueue或已排序的LinkedList(使用Comparator)?
我希望对所有项目进行排序。插入将非常频繁,并且我将不得不运行所有列表来进行一些操作。
答案 0 :(得分:27)
LinkedList
是最糟糕的选择。使用ArrayList
(或更常见的是RandomAccess
实施者)或PriorityQueue
。如果使用列表,则只在迭代其内容之前对其进行排序,而不是在每次插入之后对其进行排序。
需要注意的一点是,PriorityQueue
迭代器不按顺序提供元素;你实际上必须删除元素(清空队列)以按顺序迭代它的元素。
答案 1 :(得分:5)
您应该实施两者,然后对实际数据进行性能测试,以确定哪种方法在特定情况下效果最佳。
答案 2 :(得分:3)
我在这个问题上做了一个小基准。如果您希望在所有插入结束后对列表进行排序,那么PriorityQueue
和LinkedList
之间几乎没有差异(LinkedList有点好,从5到10)我的机器上的百分比更快,但是如果你使用ArrayList,你的排序速度将比在PriorityQueue中快2倍。
在我的列表基准测试中,我测量了从填充值开始直到排序结束的时间。对于PriorityQueue - 从填充开始到轮询结束所有元素(因为元素在PriorityQueue中按顺序排序,同时按照 erickson 回答中提到的那样删除它们)
答案 3 :(得分:2)
如果您使用LinkedList
,则每次添加项目时都需要使用项目,因为插入频繁,我不会使用LinkedList
。所以在这种情况下,我会使用PriorityQueue
'如果您只将唯一元素添加到列表中,我建议使用SortedSet
(一个实现是TreeSet
)。< / p>
答案 4 :(得分:1)
两种数据结构之间存在根本区别,它们并不像您想象的那样容易互换。
根据PriorityQueue文档:
方法iterator()中提供的迭代器不保证以任何特定顺序遍历优先级队列的元素。
使用ArrayList并在迭代列表之前调用Collections.sort()。
答案 5 :(得分:1)
PriorityQueue
的问题是您必须清空队列才能按顺序获取元素。如果这是你想要的那么它是一个很好的选择。否则,您可以使用仅在需要排序结果时排序的ArrayList
,或者如果项目不同(相对于比较器),则TreeSet
。 TreeSet
和ArrayList
在空间方面都不是很“重”;哪个更快取决于用例。
答案 6 :(得分:1)
将对象添加到优先级队列将是O log(n),并且对于每个pol都是相同的。如果您经常在非常大的队列上进行插入,那么这可能会影响性能。插入到ArrayList的顶部是不变的,因此总的来说,所有这些插入在ArrayList上的速度要比在优先级队列上快。
如果您需要按排序顺序获取所有元素,则Collections.sort将在大约O n log(n)时间内工作。其中来自优先级队列的每个pol将是O log(n)时间,因此如果你从队列中获取所有n个东西,那将再次是O n log(n)。
优先级队列获胜的用例是,如果您尝试在任何给定时间查找队列中的最大值。要使用ArrayList执行此操作,您必须在每次想要了解最大列表时对整个列表进行排序。但是通过优先级队列,它总是知道最大值是什么。
答案 7 :(得分:0)
您是否需要随时分类?如果是这种情况,您可能想要使用树集(或其他具有快速查找的SortedSet)。
如果您只需要偶尔对其进行排序,请使用链接列表并在需要访问时对其进行排序。当您不需要访问权限时,请将其排除。
答案 8 :(得分:0)
java.util.PriorityQueue
是
“基于的无限优先级队列 优先级堆“
。堆数据结构比链表更有意义
答案 9 :(得分:0)
我可以看到两个选项,哪个更好取决于您是否需要能够重复项目。
如果您不需要在列表中维护重复项,我会使用SortedSet(可能是TreeSet)。
如果您需要维护重复的项目,我会使用LinkedList并按正确的顺序将新项目插入到列表中。
除非您想在每次操作时删除项目,否则PriorityQueue并不适合。
与其他人一起确保您使用性能分析以确保为您的特定问题选择正确的解决方案。
答案 10 :(得分:-1)
恕我直言:如果有LinkedList,我们不需要PriorityQueue。我可以使用LinkedList对队列进行排序,而不是使用PriorityQueue。 e.g。
Queue list = new PriorityQueue();
list.add("1");
list.add("3");
list.add("2");
while(list.size() > 0) {
String s = list.poll().toString();
System.out.println(s);
}
我相信这段代码的工作时间太长,因为每次添加元素都会对元素进行排序。但如果我将使用下一个代码:
Queue list = new LinkedList();
list.add("1");
list.add("3");
list.add("2");
List lst = (List)list;
Collections.sort(lst);
while(list.size() > 0) {
String s = list.poll().toString();
System.out.println(s);
}
我认为此代码只会排序一次,使用PriorityQueue会更快。所以,在任何情况下,我可以在使用它之前对LinkedList进行一次排序,它会更快地运行。即使它在同一时间排序我并不真正需要PriorityQueue,我们真的不需要这个课程。