【问题标题】:While sorting the map based on value, some values are missing. What causes this weird behaviour?根据值对地图进行排序时,缺少一些值。是什么导致了这种奇怪的行为?
【发布时间】:2014-12-27 08:31:57
【问题描述】:

我正在尝试根据词频(即基于值)对地图进行排序。为此我重写了比较器并传递给TreeMap,但我得到了这个奇怪的输出。

public class WordFrequency {
    public static String sentence = "one three two two three three four four four";
    public static Map<String, Integer> map;

    public static void main(String[] args) {
        map = new HashMap<>();
        String[] words = sentence.split("\\s");

        for (String word : words) {
            Integer count = map.get(word);
            if (count == null) {
                count = 1;
            } else {
                ++count;
            }
            map.put(word, count);
        }

        Comparator<String> myComparator = new Comparator<String>() {

            @Override
            public int compare(String s1, String s2) {
                if (map.get(s1) < map.get(s2)) {
                    return -1;
                } else if (map.get(s1) > map.get(s2)) {
                    return 1;
                } else {
                    return 0;
                }
            }

        };
        SortedMap<String, Integer> sortedMap = new TreeMap<String, Integer>(myComparator);
        System.out.println("Before sorting: " + map);
        sortedMap.putAll(map);
        System.out.println("After Sorting based on value:" + sortedMap);

    }
}

输出:

Before sorting: {two=2, one=1, three=3, four=3}
After sorting based on value:{one=1, two=2, three=3}

预期输出:

{one=1, two=2, four=3,three=3}

【问题讨论】:

  • 这有什么奇怪的?
  • 可能 TreeMap 不允许重复
  • @SotiriosDelimanolis 四=3 排序后丢失
  • 你的Comparator 是如何工作的,究竟
  • @SagarPudi SotiriosDelimanolis 的 cmets 通常要求您思考并检查您当前的代码以自行获得答案。

标签: java collections map treemap


【解决方案1】:

这是因为您的实现告诉 TreeMap map[three] 和 map[four] 本质上是相同的元素,因为根据您的比较器,它们彼此“相等”。

将 Comparator 中的“return 0”改为“return s1.compareTo(s2)”,就可以了

Before sorting: {two=2, one=1, three=3, four=3}
After Sorting based on value:{one=1, two=2, four=3, three=3}

(我相信您可以弄清楚为什么在这种情况下“四”在“三”之前)

【讨论】:

    【解决方案2】:

    您的compare 方法未能遵守 Map 接口的约定,因为它比较的是值而不是键。您的实现导致具有相同值的两个键被视为相同的键。因此,您的 sortedMap 不包含“四”键,它与“三”键具有相同的值。

    请注意,由树形图维护的排序,与任何排序图一样,并且无论是否提供显式比较器,如果该排序图正确,则必须与 equals 保持一致实现地图接口。 (参见 Comparable 或 Comparator 以了解与 equals 一致的精确定义。) 之所以如此,是因为 Map 接口是根据 equals 操作定义的,但排序后的 map 使用其 compareTo(或 compare)方法执行所有键比较,因此从排序映射的角度来看,此方法认为相等的两个键是相等的。已排序映射的行为是明确定义的,即使它的排序与 equals 不一致;它只是不遵守 Map 接口的一般约定。

    TreeMap reference

    您可以通过在值相等时比较键来解决此问题:

        Comparator<String> myComparator = new Comparator<String>() {
    
            @Override
            public int compare(String s1, String s2) {
                if (map.get(s1) < map.get(s2)) {
                    return -1;
                } else if (map.get(s1) > map.get(s2)) {
                    return 1;
                } else {
                    return s1.compareTo(s2);
                }
            }
    
        };
    

    这应该会给你一个输出:

    After sorting based on value:{one=1, two=2, four=3, three=3}
    

    由于four&lt;three基于字符串的自然排序。

    【讨论】:

      【解决方案3】:

      因为您的 compare() 仅考虑 Map 中的值。那么three=3, four=3 具有相同的值3。然后,当他们添加到 TreeMap 时,它们会被视为重复。

      【讨论】:

        猜你喜欢
        • 2011-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-18
        • 1970-01-01
        • 1970-01-01
        • 2015-11-07
        相关资源
        最近更新 更多