我编写了一个方法,用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;
}
以上工作正常,但我无法理解为什么第一种方法不起作用。为什么删除重复值输入?有人可以让我知道吗
答案 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;
正确的比较器必须遵循三条规则:
compare(a, a) == 0
代表a
的所有值。signum(compare(a, b)) == -signum(compare(b, a))
代表a
和b
的所有值。signum(compare(a, b)) == signum(compare(b, c))
,则signum(compare(a, c))
对a
,b
和c
的所有值都必须具有相同的值。