按值排序地图,需要澄清



我知道,这个问题已经问了好几次了,但帮助我理解一些东西。

您有一张需要按价值排序的地图

    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,则应为-1Comparator约定指定,如果第一个值小于第二个值,则返回负数;如果第一个大于第二个,则返回正数;如果相等,则返回零。

(请注意,目前的情况是,如果您碰巧使用了原始映射中没有的值,那么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;
}

最新更新