使用新比较器时TreeMap问题

时间:2015-07-17 07:05:58

标签: java

TreeMap<String, Integer> map1 = new TreeMap<String, Integer>();
map1.put("A", 1); map1.put("B", 2); map1.put("C", 3);
TreeMap<String, Integer> map2 = new TreeMap<>((str1, str2) -> map1.get(str1) - map1.get(str2) > 0 ? -1 : 1);
map2.putAll(map1);
Iterator<String> iterator = map2.keySet().iterator();
    while(iterator.hasNext()) {
        String key = iterator.next();
        System.out.println(key + "  " + map2.get(key) + " " + map1.get(key));
}

输出

C  null 3

B  null 2

A  null 1

请解释为什么我从map2获取空值,即使在map2.putAll(map1)

之后

奇怪的是,当我遍历条目时,迭代器正在提供正确的输出

    Iterator<Entry<String, Integer>> entryIterator = map2.entrySet().iterator();
    while(entryIterator.hasNext()) {
        Entry<String, Integer> entry = entryIterator.next();
        System.out.println(entry.getKey() + " " + entry.getValue());
    }

EDIT 正如所回答的问题是与比较它正在与

一起使用
    TreeMap<String, Integer> map2 = new TreeMap<>((str1, str2) -> str1.equals(str2) ? 0 : map1.get(str1) - map1.get(str2) > 0 ? -1 : 1);

2 个答案:

答案 0 :(得分:2)

当地图值相等时,您错过了在比较器中返回零:

TreeMap<String, Integer> map2 = new TreeMap<>(
    new Comparator<String>() {

        @Override
        public int compare(String str1, String str2) {
            if(map1.get(str1).equals(map1.get(str2))) {
                return 0;
            }
            return map1.get(str1) - map1.get(str2) > 0 ? -1 : 1;
        }
    });

来自TreeMap的文档:

  

请注意,树映射维护的顺序(如任何有序映射)以及是否提供显式比较器必须equals 一致,如果此有序映射是正确实现Map接口。 (有关与equals 一致的精确定义,请参阅ComparableComparator。)这是因为Map接口是根据{{1操作,但是有序地图使用其equals(或compareTo)方法执行所有关键比较,因此通过此方法认为相同的两个关键字来自有序地图的立场,相等。即使排序与compare不一致,也可以很好地定义有序映射的行为。它只是没有遵守equals接口的一般合同。

答案 1 :(得分:0)

检查TreeMap源代码

final Entry<K,V> getEntryUsingComparator(Object key) {
    @SuppressWarnings("unchecked")
        K k = (K) key;
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = cpr.compare(k, p.key);
            if (cmp < 0)
                p = p.left;
            else if (cmp > 0)
                p = p.right;
            else
                return p;
        }
    }
    return null;
}

它使用比较器来获取条目,就像二进制搜索一样。 你的比较器返回0,然后TreeMap永远找不到该条目,所以返回null。