我知道,这个问题已经问了好几次了,但帮助我理解一些东西。
您有一张需要按价值排序的地图
Map<String, Integer> m = new HashMap<String, Integer>();
m.put("a", 1);
m.put("b", 13);
m.put("c", 22);
m.put("d", 2);
你调用一个方法来实现
public static List<String> sortByValue(final Map<String, Integer> unsortedMap) {
List<String> sortedKeys = new ArrayList<String>();
sortedKeys.addAll(unsortedMap.keySet());
Collections.sort(sortedKeys, new MapComparator(unsortedMap));
return sortedKeys;
}
你有一个比较类
public MapComparator(Map<String, Integer> m) {
this.m = m;
}
@Override
public int compare(String a, String b) {
int x = m.get(a);
int y = m.get(b);
if (x > y)
return x;
if (y > x)
return y;
return 0;
}
这个代码显然是有缺陷的。请帮我理解为什么?
if (x > y)
return x;
if (y > x)
return y;
return 0;
如果是x > y
,则应返回1
;如果是y > x
,则应为-1
。Comparator
约定指定,如果第一个值小于第二个值,则返回负数;如果第一个大于第二个,则返回正数;如果相等,则返回零。
(请注意,目前的情况是,如果您碰巧使用了原始映射中没有的值,那么Comparator
实现将以非常令人困惑的方式崩溃。)
更好的是,只需返回Integer.compare(x, y)
,它就可以为您完成所有这些。(不过,仅在Java 7中。)
@Override
public int compare(String a, String b) {
Integer x = m.get(a);
Integer y = m.get(b);
return x.compareTo(y);
}
由于有Integer对象作为值,因此可以使用隐式方法比较对象并返回1、0或-1。
比较器不会返回较大或较小的值。它们返回负值表示小于或返回正值表示大于。
if (x > y)
return x;
if (y > x)
return y;
return 0;
应该是
if (x > y)
return -1;
if (y > x)
return 1;
return 0;
您的比较器只指示值相等或左大于右。
考虑x
是1并且y
是2的情况。您的比较器将返回2—正数—当它应该返回一个负数时。
我建议您再次研究Comparator
接口文档,看看您错过了合同的哪一部分。
public static List<String> sortByValue(final Map<String, Integer> unsortedMap) {
List<String> sortedKeys = new ArrayList<String>();
sortedKeys.addAll(unsortedMap.keySet());
Collections.sort(sortedKeys, new Comparator<String>(){
public int compare(String s1, String s2) {
return unsortedMap.get(s1).compareTo(unsortedMap.get(s2));
}});
return sortedKeys;
}