按值排序地图,需要澄清

时间:2012-02-07 03:15:04

标签: java comparator

我知道,已经多次询问过这个问题,但帮助我理解了一些事情。

您有一张需要按价值

排序的地图
    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;

}

这段代码显然是有缺陷的。请帮我理解原因?

5 个答案:

答案 0 :(得分:2)

  if (x > y)
    return x;
  if (y > x)
    return y;

  return 0;

如果1,您应该返回x > y,如果-1则返回y > xComparator合约指定如果第一个值小于第二个值则返回负数,如果第一个值大于第二个值则返回正数,如果它们相等则返回零。

(请注意,如果你曾经碰巧使用原始地图中没有的值,这个Comparator实现会以非常混乱的方式破解。)

更好的是,只需返回Integer.compare(x, y),即可完成所有这些操作。 (但是只在Java 7中。)

答案 1 :(得分:1)

@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。

答案 2 :(得分:0)

比较器不会返回更大或更小的值。它们返回一个负值,表示小于或正值表示大于。

if (x > y)
    return x;
if (y > x)
    return y;

return 0;

应该是

if (x > y)
    return -1;
if (y > x)
    return 1;

return 0;

答案 3 :(得分:0)

您的比较器仅表示值相等或左侧大于右侧。

考虑x为1且y为2的情况。比较器将返回2 - 正数 - 当它应该返回负数时。

我建议你再次学习the Comparator interface documentation,看看你错过了合同的哪一部分。

答案 4 :(得分:0)

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;
}