java - Java中优先级队列中的自定义比较器
问题描述
我正在尝试将优先级队列与自定义比较器一起使用,但是我无法实现预期的功能。:
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
public class TestMain {
public static void main(String[] args) {
Queue<Node> queue = new PriorityQueue<>(new Comparator<Node>() {
public int compare(Node a, Node b) {
if(a.level == b.level) {
return a.data - b.data;
}
return a.level - b.level;
}
});
queue.add(new Node(0,1));
queue.add(new Node(1,2));
queue.add(new Node(1,4));
queue.add(new Node(2,3));
queue.add(new Node(2,7));
queue.add(new Node(2,2));
queue.add(new Node(2,5));
System.out.println(queue);
}
private static class Node {
int level;
int data;
Node(int level, int data) {
this.level = level;
this.data = data;
}
public String toString() {
return level + ":" + data;
}
}
}
预期产出 =[0:1, 1:2, 1:4, 2:2, 2:3, 2:5, 2:7]
实际产出 =[0:1, 1:2, 1:4, 2:3, 2:7, 2:2, 2:5]
我希望优先级队列中的元素首先按级别排序,然后按数据排序。
解决方案
toString 方法可能不会按检索顺序显示元素。因此,这并不意味着您的比较器不正确。
以下是在PriorityQueu 的 javadoc中编写的(重点是我的):
此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选方法。方法 iterator() 中提供的 Iterator 和方法 spliterator() 中提供的 Spliterator 不能保证以任何特定顺序遍历优先级队列的元素。如果您需要有序遍历,请考虑使用 Arrays.sort(pq.toArray())。
这里没有明确写出来,但是 toString 依赖于迭代器,因此元素也可能不会以预期的方式显示。toString 方法是在类 Collection 中定义的,这里没有特别重写。
PriorityQueu 可能是使用数组中的二进制堆实现的。从那里,很自然地,迭代是按数组顺序进行的。以正确的顺序显示元素需要将它们从队列中删除,因此除了在其他地方排序副本之外是不可能的,这对于简单的 toString 来说太重了。
推荐阅读
- spring - Spring Conditional SpEL 无法解析
- tensorflow - InvalidArgumentError:无法序列化 tensorflow.GraphDef 类型的协议缓冲区
- python - 无法安装/更新任何包/conda/navigator?
- flowtype - 如何在 React HOC 中描述流移除道具
- javascript - js 事件,如果用户点击浏览器的上下文菜单
- circuit-sdk - 电路 API 问题
- callback - RabbitMQ 是否为消费者保持开放连接?
- javascript - 当我将目的地设置为另存为 PDF 时,window.print() 不显示更多设置
- swift - 在模拟器上运行时出现链接器错误,可以在设备上运行,有人可以帮我解决这个问题吗?
- linux - 线程级并行 VS 进程级并行