我正在尝试根据词频(即基于值)对地图进行排序。为此,我已经重写了比较器并传递给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);
}
}
Output:
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}
Your compare
方法无法遵守 Map 接口的约定,因为它比较的是值而不是键。您的实现会导致具有相同值的两个键被视为相同的键。因此你的sortedMap
不包含“四”键,该键与“三”键具有相同的值。
注意由树图维护的顺序,就像任何排序的映射一样,无论是否提供显式比较器,如果这个排序的map要正确实现Map接口就必须和equals一致。 (有关与 equals 一致的精确定义,请参阅 Comparable 或 Comparator。)之所以如此,是因为 Map 接口是根据 equals 操作定义的,但排序映射使用其compareTo(或compare)方法执行所有键比较, so 从排序映射的角度来看,此方法认为相等的两个键是相等的。即使排序与 equals 不一致,排序映射的行为也是明确定义的;它只是没有遵守 Map 接口的一般契约。
树形图参考 http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
您可以通过在值相等时比较键来解决此问题:
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}
Since four<three
基于字符串的自然排序。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)