Java TreeMap包含一个键,但containsKey调用返回false(即使键是完全相同的未更改对象)

时间:2013-08-07 17:16:32

标签: java map treemap containskey keyset

为什么可以循环TreeMap的keySet并获得.containsKey == false

for (Object thisObject : map.keySet()) {
    if (!map.containsKey(thisObject)) {
        System.out.println("This line should be never reached.");
    }
}

经过很多次,很多不同的迭代和调用此行被击中。 map.get(thisObject)将返回null。 但是调试显示键(相同的引用,值和哈希)和实际值在地图中。地图是一个小的(25个元素)TreeMap<Long, Double>

更新

正如@rgettman所猜测的那样,在构造TreeMap时使用的自定义排序Comparator(没有看到它,因为它是从另一个类构造的)。这个比较器只是(我猜)从here

复制粘贴

更改Comparator

  public int compare(Object a, Object b) {

    if((Double)base.get(a) > (Double)base.get(b)) {
      return 1;
    } else if((Double)base.get(a) == (Double)base.get(b)) {
      return 0;
    } else {
      return -1;
    }
  }

...
    } else if(base.get(a).equals(base.get(b))) {
      return 0;
...

解决了这个问题。在数百万次操作之后出现这个问题的原因是没有情况下地图有两个不同键的两个相似值,因为这在上下文中是不太可能的。

所以:

25151l, 1.7583805400614032
24827l, 1.7583805400614032

失败了。

感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

我刚刚执行了代码,此案例返回true 给我。

          TreeMap<Long,Double> otm = new TreeMap<Long, Double>();
          otm.put(1L, 1.0);
          otm.put(2L, 2.0);

        for (Object thisObject : otm.keySet()) {
                System.out.println(otm.containsKey(thisObject));
        }     

您能否告诉我们您在TreeMap中输入的数据。感谢

这是来自JavaDocs的containsKey(Object key)实现

  

containsKey

     

<强>布尔的containsKey(对象键)

     

如果此映射包含指定键的映射,则返回true。

     

更正式地说,当且仅当此地图包含映射时才返回true   对于一个关键的k,    (key == null?k == null:key.equals(k))。 (那里   最多只能有一个这样的映射。)

参数:

key - key whose presence in this map is to be tested Returns:
true if this map contains a mapping for the specified key Throws:
ClassCastException - if the key is of an inappropriate type for this map (optional)
NullPointerException - if the specified key is null and this map does not permit null keys (optional

希望有所帮助。

答案 1 :(得分:0)

您必须对支持entrySet()/Map.Entry进行更改,从而更改关键订单,从而导致搜索失败containsKey

答案 2 :(得分:0)

这些实现类中的大多数依赖于hashCode()和equals()支持且正确。

如果您确实从对象获得相同的哈希码,请尝试匹配相等。我建议的答案是它们不匹配。

否则,该场景应该足够小,以便您发布对象和/或它们各自的hashcode和equals方法。