【发布时间】:2012-11-30 22:08:25
【问题描述】:
我正在寻找按值对Map<String, Integer> 进行排序的方法。我找到了this post,它解决了我的排序问题,但不完全是。根据帖子,我写了以下代码:
import java.util.*;
public class Sort {
static class ValueComparator implements Comparator<String> {
Map<String, Integer> base;
ValueComparator(Map<String, Integer> base) {
this.base = base;
}
@Override
public int compare(String a, String b) {
if (base.get(a) >= base.get(b)) {
return 1;
} else {
return -1;
}
}
}
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
ValueComparator vc = new ValueComparator(map);
TreeMap<String, Integer> sorted = new TreeMap<String, Integer>(vc);
map.put("A", 1);
map.put("B", 2);
sorted.putAll(map);
for (String key : sorted.keySet()) {
System.out.println(key + " : " + sorted.get(key)); // why null values here?
}
System.out.println(sorted.values()); // But we do have non-null values here!
}
}
输出:
A : null
B : null
[1, 2]
BUILD SUCCESSFUL (total time: 0 seconds)
从输出中可以看出,get 方法总是返回 null。原因是我的ValueComparator.compare() 方法永远不会返回0,这是我通过制作this post 发现的。
有人在那篇帖子中建议以下解决null值问题:
public int compare(String a, String b) {
if (base.get(a) > base.get(b)) {
return 1;
}else if(base.get(a) == base.get(b)){
return 0;
}
return -1;
}
我已经测试了这段代码,它引入了一个关键的合并问题。换句话说,当值相等时,它们对应的键被合并。
我还尝试了以下方法:
public int compare(String a, String b) {
if (a.equals(b)) return 0;
if (base.get(a) >= base.get(b)) {
return 1;
} else return -1;
}
它也不起作用。一些值仍然是null。此外,这种解决方法可能存在逻辑问题。
任何人都可以为我的问题提出一个完全可行的解决方案吗?我希望按值排序函数和get 方法同时工作。
【问题讨论】:
-
为什么/如何按值对地图进行排序?我认为这甚至没有意义……这不就是 Lists 和 Sets 的用途吗?只需调用 Map.values() 并将结果添加到 TreeSet 或有序 List。
-
@jahroy 您如何将排序后的值与其对应的键关联起来?我不想手动维护键和值之间的关系。
-
OK... 所以您希望根据值的顺序对 键 进行排序。我猜我明白你现在想要什么了。
-
在这种情况下,你应该使用这个:
return base.get(a).compareTo(base.get(b)) -
@jahroy 如果您有比使用地图更好的解决方案,那也很好:)
标签: java sorting hashmap comparator treemap