我以这个问题为出发点:
Add Key and Value into an Priority Queue and Sort by Key in Java
我有类似的情况,我的POJO的PQ有两个重要的属性:键和值。
但是,在我向PQ添加新条目之前,首先我要检查PQ中是否已存在具有相同密钥的条目。在这种情况下,我希望增加其值。我该怎么做呢?
答案 0 :(得分:1)
javadoc说明了这一点。
强烈建议,但并非严格要求(x.compareTo(y)== 0)==(x.equals(y))
但同样,这不是必要的。有必要覆盖方法public boolean equals(Object entry)
以使方法contains()
起作用,而不是声明方法public boolean equals(Entry entry)
。
你应该有equals()
类似的。
@Override
public boolean equals(Object entry) {
if (entry instanceof Entry) return this.key == ((Entry) entry).key;
else return false;
}
另外要考虑的是,当对象已经存在于已排序/哈希的集合中时,对该对象进行变异是一个可怕的想法。这会导致奇怪的行为。我会告诉你一个例子。
在条目中使用toString()
方法。
@Override
public String toString() {
return String.format("{ %d, %d }", key, value);
}
使用此代码打印优先级队列。
PriorityQueue<Entry> queue = new PriorityQueue<>();
for (Entry data : entries) {
Entry entry = new Entry(data.getKey(), data.getValue());
if (queue.contains(entry)) {
for (Entry current : queue) { // just for the example
if (current.equals(entry)) {
current.addToValue(entry.getValue());
}
}
} else {
queue.add(entry);
}
}
while (!queue.isEmpty()) // print ordered
System.out.println(queue.poll());
有了这些数据。
List<Entry> entries = Arrays.asList(
new Entry(1, 4),
new Entry(2, 3),
new Entry(2, 5)
);
输出未正确排序{ 1, 4 }, { 2, 8 }
而不是{ 2, 8 }, { 1, 4 }
,这是因为id为2的条目在添加到集合后会发生变异。
另一方面,有了这个数据
List<Entry> entries = Arrays.asList(
new Entry(1, 4),
new Entry(2, 8)
);
它打印输出正确排序{ 2, 8 }, { 1, 4 }
。
Map<Integer, Integer> map = new HashMap<>();
for (Entry data : entries) { // here instead read from csv and create entry
map.computeIfPresent(data.getKey(), (k, v) -> v + data.getValue()); // sum priorities
map.putIfAbsent(data.getKey(), data.getValue()); // add when not exists
}
现在您有一个由键标识的映射并包含优先级的sumarized值,您可以使用TreeSet或PriorityQueue对条目进行排序。
您不需要使用自定义条目,您可以使用java Entry并将Comparator传递给TreeSet / PriorityQueue。
TreeSet<Map.Entry<Integer, Integer>> treeSet = new TreeSet<>((e1, e2) ->
e2.getValue() - e1.getValue() != 0 ?
e2.getValue() - e1.getValue() :
e2.getKey() - e1.getKey());
treeSet.addAll(map.entrySet());
System.out.println(treeSet);
此比较器首先比较优先级,如果不同,则按照后代顺序返回-1或1。
如果优先级相同,则比较密钥,并返回-1或1(因为没有重复的密钥,因此不能执行0),并且密钥的顺序正在下降。