Java:PriorityQueue 从自定义比较器返回不正确的顺序? [复制]
Posted
技术标签:
【中文标题】Java:PriorityQueue 从自定义比较器返回不正确的顺序? [复制]【英文标题】:Java: PriorityQueue returning incorrect ordering from custom comparator? [duplicate] 【发布时间】:2010-06-15 19:50:46 【问题描述】:我编写了一个自定义比较器来比较我的节点类,但是 java 优先级队列没有以正确的顺序返回我的项目。
这是我的比较器:
public int compare(Node n1, Node n2)
if (n1.getF() > n2.getF())
return +1;
else if (n1.getF() < n2.getF())
return -1;
else // equal
return 0;
其中 getF 返回一个双精度值。然而,在将几个节点插入优先级队列后,我使用以下命令将它们打印出来:
while(open.size() > 0)
Node t = (Node)(open.remove());
System.out.println(t.getF());
结果:
6.830951894845301
6.830951894845301
6.0
6.0
5.242640687119285
7.4031242374328485
7.4031242374328485
8.071067811865476
任何想法为什么会这样?我的比较器错了吗?谢谢。
迈克
【问题讨论】:
您的“Java 优先级队列”是什么实际的 Java 类(我假设是 PriorityQueue),您是如何构建它的? java.util.PriorityQueue,我猜? 没有回答您的问题,但我注意到您可以将比较器简化为:return Double.compare(n1.getF(), n2.getF());
@Gray - 这就是我声明它的方式: Comparator您如何打印出这些值?我不认为来自PriorityQueue
的迭代器提供了与整个类相同的排序保证,如果你正在这样做,那么可能
for(Node n : queue)
System.out.println(n.getF());
你会得到无序的输出。订购保证仅适用于offer
、take
、poll
、peek
,可能还有其他一些方法。
javadocs 中特别提到了优先级队列 @987654321@ 的迭代器
【讨论】:
没错;来自PriorityQueue
javadoc 的iterator()
方法:“迭代器不会以任何特定顺序返回元素。”
“你是如何打印出这些值的?”......问题是“我用......打印出来”。
我没有使用迭代器。 Comparator不知道你的代码有什么问题,但这对我有用:
import java.util.*;
public class Test
public static void main(String[] args)
PriorityQueue<Node> open = new PriorityQueue<Node>(10,
new Comparator<Node>()
@Override
public int compare(Node n1, Node n2)
if (n1.getF() > n2.getF())
return +1;
else if (n1.getF() < n2.getF())
return -1;
else // equal
return 0;
);
for (int i = 0; i < 20; i++)
open.add(new Node());
while(open.size() > 0)
Node t = (Node)(open.remove());
System.out.println(t.getF());
class Node
double d = Math.random() * 10;
public double getF() return d;
输出:
0.21442281608773262
1.9965384843480016
2.6660026888929824
2.888889937975976
3.098932914222398
3.1059072964534638
4.193212975907516
4.296282412431935
4.3241392173963735
4.825876226139123
5.193550353435191
5.637831708672641
5.949759449054407
6.620639629878806
7.505126870725806
7.966337123623846
8.270840212631589
8.484502118941545
8.730910327480023
9.191324325662219
确保 getF()
不会意外返回双精度的 int 版本。
更新:您不能更新定义插入后元素顺序的数据。在这种情况下,您需要提取元素、更新它并重新插入它。
【讨论】:
你可以尝试使用类迭代器吗?看看你是否得到无序输出? 那么它的排序不正确。说得通。如果它被实现为一个堆,它所知道的就是下一个要删除的元素是。 嗯...我先将节点添加到prio队列中,然后使用节点的“setF”函数更改f值。插入对象后,prio 队列中的值是否没有更新?即使我指向优先队列中的节点? @Ceilingfish - 我的节点类将 f 值初始化为 -1,然后插入 prio 队列,然后更新 f val。这与您上面的示例不同。感谢您仔细检查基本逻辑,谢谢。 PriorityQueue 将数据插入到正确的位置。数据在被轮询之前不会被使用。如果您在插入后更改数据,则不会对其进行排序。 Jacob,您可能应该将此评论转化为答案,这样您就可以得到赞誉(当然,查看问题的人也知道在哪里可以找到答案)以上是关于Java:PriorityQueue 从自定义比较器返回不正确的顺序? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
Java 中的比较器和 PriorityQueue 是如何工作的?
是否有具有固定容量和自定义比较器的 PriorityQueue 实现?
Java中的Collection和Map--PriorityQueue