我一直在寻找按值排序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
方法同时工作。
答案 0 :(得分:6)
在比较功能中,当值相等时,您应该比较这些键。这将确保具有相同值的不同键不会被“合并”,因为它消除了本来比较相等的条目的歧义。
例如:
@Override
public int compare(String a, String b) {
Integer x = base.get(a);
Integer y = base.get(b);
if (x.equals(y)) {
return a.compareTo(b);
}
return x.compareTo(y);
}
(您需要修改上面的代码以匹配您的空值策略)
请注意,您对值进行排序的方法非常脆弱。您的“已排序”地图不支持添加新条目,这可能会令人困惑。
答案 1 :(得分:4)
base.get(a) == base.get(b)
此代码通过引用比较加框的Integer
。
将其更改为base.get(a).equals(base.get(b))
,它应该有效。
答案 2 :(得分:1)
试试这个:
return base.get(a).compareTo(base.get(b));
要证明您对自动取消装箱不正确:
Integer a = new Integer(2);
Integer b = new Integer(2);
boolean isEqual = ( a == b );
System.out.println("equal: " + isEqual);
System.out.println("a: " + a);
System.out.println("b: " + b);
我的输出是:
equal: false
a: 2
b: 2
答案 3 :(得分:1)
试试这个......
HashMap<String, Integer> h = new HashMap<String, Integer>();
h.put("z",30);
h.put("e",10);
h.put("b",20);
h.put("c",20);
List<Map.Entry> a = new ArrayList<Map.Entry>(h.entrySet());
Collections.sort(a,
new Comparator() {
public int compare(Object o1, Object o2) {
Map.Entry e1 = (Map.Entry) o1;
Map.Entry e2 = (Map.Entry) o2;
return ((Comparable) e1.getValue()).compareTo(e2.getValue());
}
});
for (Map.Entry e : a) {
System.out.println(e.getKey() + " " + e.getValue());
}
输出:
e 10
b 20
c 20
z 30