在基于值对地图排序时,缺少一些值。是什么原因导致这种奇怪的行为? [英] While sorting the map based on value, some values are missing. What causes this weird behaviour?

查看:148
本文介绍了在基于值对地图排序时,缺少一些值。是什么原因导致这种奇怪的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想根据字词频率(即基于值)对地图进行排序。因为我已经覆盖了比较器并传递给 TreeMap ,但我得到这个奇怪的输出。

  public class WordFrequency {
public static String sentence =一三二二三三四四四;
public static Map< String,Integer>地图;

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

比较器< 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(基于值排序后:+ sortedMap);

}
}

输出:



在排序之前:{two = 2,one = 1,three = 3,four = 3}
基于值排序后:{ one = 1,two = 2,three = 3}

预期输出:

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


解决方案

您的比较方法未能遵守Map界面的合同,因为它比较值而不是键。您的实现导致具有相同值的两个键被认为是相同的键。因此,您的 sortedMap 不包含four键,其值与three键相同。


请注意,由树状图维护的排序(如任何排序的地图),以及是否提供显式比较器,必须与equals如果此排序的映射要正确实现Map接口。 (请参阅Comparable或Comparator以获取与equals一致的精确定义)这是因为Map接口是使用equals操作定义的,但是排序映射使用compareTo(或compare)方法执行所有键比较,因此从排序地图的角度来看,通过此方法视为相等的两个键等于。排序映射的行为是明确定义的,即使其排序与equals不一致;它只是没有遵守Map接口的一般合同。


TreeMap参考



您可以通过当值相等时比较键:

 比较器< 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);
}
}

};

这将给你一个输出:

 基于值排序后:{one = 1,two = 2,four = 3,three = 3} 

因为四<3 基于字符串的自然排序。


I am trying to sort a map based on word frequency (i.e., based on value). For that I have overridden comparator and passed to TreeMap, but I am getting this weird output.

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

    }
}

Output:

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

Expected Output:

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

解决方案

Your compare method fails to obey the contract of the Map interface, since it compares values instead of keys. Your implementation causes two keys with the same value to be considered the same key. Therefore your sortedMap doesn't contain the "four" key, which has the same value as the "three" key.

Note that the ordering maintained by a tree map, like any sorted map, and whether or not an explicit comparator is provided, must be consistent with equals if this sorted map is to correctly implement the Map interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Map interface is defined in terms of the equals operation, but a sorted map performs all key comparisons using its compareTo (or compare) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. The behavior of a sorted map is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Map interface.

TreeMap reference

You can fix this problem by comparing the keys when the values are equal :

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

    };

This should give you an output of :

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

Since four<three based on the natural ordering of Strings.

这篇关于在基于值对地图排序时,缺少一些值。是什么原因导致这种奇怪的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆