【发布时间】:2014-10-23 09:43:38
【问题描述】:
我有一个 NodeWeightWrapper 包装器来包装 Node 对象及其关联的 weight。下面是包装器的代码。我在weight 上实现了Comparable 并覆盖了compareTo 方法,因此我可以在优先级队列中使用包装器对象。
public class NodeWeightWrapper implements Comparable<NodeWeightWrapper> {
private final Node node;
private int weight;
public NodeWeightWrapper(Node node, int weight) {
this.node = node;
this.weight = weight;
}
public Node getNode() {
return node;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public int compareTo(NodeWeightWrapper o) {
return Integer.compare(this.getWeight(), o.getWeight());
}
}
将对象添加到优先队列
PriorityQueue<NodeWeightWrapper> freeNodes = new PriorityQueue<>();
freeNodes.add(new NodeWeightWrapper(nodeA, 20));
freeNodes.add(new NodeWeightWrapper(nodeB, 15));
freeNodes.add(new NodeWeightWrapper(nodeC, 10));
这是问题所在,如果我更新优先队列中对象的weight,如下所示。下次我poll 一个对象出优先级队列时,同样不会反映出来。这意味着优先队列仅在发生新插入时才对元素进行排序。因此,我尝试删除原始包装器对象并插入一个具有更新值的新包装器对象,但这会引发 ConcurrentModificationException,因为我们处于 foreach 循环中。任何我可以更新权重的建议都会反映在优先队列中。
for (NodeWeightWrapper nww : freeNodes) {
if (nww.getWeight() > value) {
nww.setWeight(value);
}
}
【问题讨论】:
-
插入一个新对象,就像你正在尝试的那样。只是不要以会导致
ConcurrentModificationException被抛出的方式进行操作(即不在 foreach 循环内)。 -
一个建议是在遍历原始队列时构建一个新的 priorityQueue。
-
您需要确保不要在循环中修改代码。将其复制到列表中以供以后包含
-
@Kayaman 但是删除和添加对象需要 O(logn) 时间。这是实现更新的有效方法吗?
标签: java data-structures priority-queue