我在 TreeMap
中使用的 Comparator
破坏了我为该 TreeMap
设计的行为。看下面的代码:
TreeMap<String, String> treeMap = new TreeMap<>(new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.toLowerCase().compareTo(o2.toLowerCase());
}
});
treeMap.put("abc", "Element1");
treeMap.put("ABC", "Element2");
我认为我所做的是我创建了一个按其键排序的 map ,不区分大小写。这两个不同的元素具有不相等的键(abc
和 ABC
),它们的比较将返回 0
。我期望这两个元素只是随机排序。然而,命令:
System.out.println("treeMap: " + treeMap);
导致:
treeMap: {abc=Element2}
键 abc
已重新分配值 Element2
!
谁能解释这是怎么发生的,以及它是否是 TreeMap
的有效的、记录在案的行为?
最佳答案
这是因为 TreeMap
认为如果 a.compareTo(b) == 0
元素相等。它记录在 the JavaDoc for TreeMap (强调我的):
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. (SeeComparable
orComparator
for a precise definition of consistent withequals
.) This is so because the Map interface is defined in terms of theequals
operation, but a sorted map performs all key comparisons using itscompareTo
(orcompare
) 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 withequals
; it just fails to obey the general contract of the Map interface.
您的比较器与 equals 不一致。
如果您想保留不等于但等于忽略大小写的元素,请在比较器中进行第二级检查,以使用区分大小写的排序:
public int compare(String o1, String o2) {
int cmp = o1.compareToIgnoreCase(o2);
if (cmp != 0) return cmp;
return o1.compareTo(o2);
}
关于java - 不区分大小写的比较器破坏了我的 TreeMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46912097/