java - 不区分大小写的比较器破坏了我的 TreeMap

标签 java comparator

我在 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 ,不区分大小写。这两个不同的元素具有不相等的键(abcABC),它们的比较将返回 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. (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.

您的比较器与 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/

相关文章:

java - Linux 上 Maven exec/debug 插件下的 Unsatisfied link 错误

java - JPanel 布局管理器

java - XML DocumentBuilder 删除 CDATA 部分

java - 使用自定义比较器(如 Excel 坐标顺序)订购 TreeMap

java - 按日期对具有 itemBean 的列表进行排序?

java - JDK 编译器优化了没有实例变量的匿名类的使用?

java - 获取 SXSSFWorkbook 的文件大小

Android SortedList 删除方法正在跳过项目

C++ 字符串像人一样排序?

模型类上反射 toString 中的 java.lang.ClassCastException : [Z cannot be cast to [Ljava. lang.String