TreeMap排序不适用于相等的值

时间:2014-07-04 05:26:26

标签: java sorting map comparator treemap

我编写了一个方法,用TreeMap对其值进行排序

public TreeMap<String, Integer> sortByValues(final TreeMap<String, Integer> map) {
        Comparator<String> valueComparator =  new Comparator<String>() {
            public int compare(String k1, String k2) {
                int compare = map.get(k1).compareTo(map.get(k2));
                return compare;
            }
        };
        Map<String, Integer> sortedByValues = new TreeMap<String, Integer>(valueComparator);
        sortedByValues.putAll(map);
        return sortedByValues;
    }

上述方法在正常情况下工作正常,但在TreeMap中存在重复值时失败。从Map中删除任何重复的值条目。在谷歌搜索后,我找到了解决方案

public Map<String, Integer> sortByValuesTree(final Map<String, Integer> map) {
        Comparator<String> valueComparator =  new Comparator<String>() {
            public int compare(String k1, String k2) {
                int compare = map.get(k1).compareTo(map.get(k2));
                if (compare == 0) return 1;
                else return compare;
            }
        };
        Map<String, Integer> sortedByValues = new TreeMap<String, Integer>(valueComparator);
        sortedByValues.putAll(map);
        return sortedByValues;
    }

以上工作正常,但我无法理解为什么第一种方法不起作用。为什么删除重复值输入?有人可以让我知道吗

2 个答案:

答案 0 :(得分:4)

  

为什么删除重复的值条目?

因为它是Map的定义:对于给定的键,它存储一个值。如果为已存在于映射中的键添加另一个值,则新值将替换此键的旧值。并且由于当关联值相等时,你告诉地图一个键等于另一个键,因此当它们的值相等时,映射会认为两个键是相等的。

请注意,您的解决方案很糟糕,可能是偶然的。实际上,您的比较器并不尊重比较器接口的合同。实际上,当两个值相等时,您可以任意决定使第一个值大于第二个值。这意味着您的比较器使A&gt; B和B&gt;同时是真的,这是不正确的。

按值对TreeMap进行排序对我来说看起来很荒谬。无论如何,您无法向地图添加任何新值,因为它需要旧地图中已存在的条目。难道你不仅仅有一个排序的地图条目列表吗?

答案 1 :(得分:3)

实际上,尤其是在Java 7以后,即使你的第二种方法也不行。 (请参阅下面的原因。)无论如何,原因是地图必须具有不同的键,当您使用值作为键时,两个相等的值将被视为相等的键。

顺便说一句,正确的解决方法是按值排序,然后按键排序:

int compare = map.get(k1).compareTo(map.get(k2));
if (compare == 0) {
    compare = k1.compareTo(k2);
}
return compare;

正确的比较器必须遵循三条规则:

  1. compare(a, a) == 0代表a的所有值。
  2. signum(compare(a, b)) == -signum(compare(b, a))代表ab的所有值。
  3. 如果signum(compare(a, b)) == signum(compare(b, c)),则signum(compare(a, c))abc的所有值都必须具有相同的值。