简体   繁体   English

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

[英]Java TreeMap contains a key but a containsKey call returns false (even the key is exactly the same unchanged object)

Why is it possible to loop the keySet of a TreeMap and getting a .containsKey == false ? 为什么可以循环TreeMap的keySet并获得.containsKey == false

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

After a lot, lot of different iterations and calls this line gets hit. 经过很多次,很多不同的迭代和调用此行被击中。 A map.get(thisObject) would return null . map.get(thisObject)将返回null But debug shows that the key ( same reference, value and hash ) and an actual value is in the map. 但调试显示密钥( 相同的引用,值和散列 )和实际值在地图中。 The map is a small (25 elements) TreeMap<Long, Double> 地图是一个小的(25个元素) TreeMap<Long, Double>

UPDATE: 更新:

As guessed by @rgettman theres a custom sort Comparator used at the construction of the TreeMap (Didn't see it because it was constructed from another class). 正如@rgettman所猜测的那样 ,在构造TreeMap时使用了一个自定义排序Comparator器(没有看到它,因为它是从另一个类构造的)。 This comparator was just (I guess) copy pasted from here 这个比较器只是(我猜)从这里复制粘贴

Changing the Comparator : 更改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;
    }
  }

to

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

fixes the problem. 解决了这个问题。 The reason why this problem was showing up just after millions of operation was that there were no cases where the map had two similar values for two different keys, as this is very unlikely in the context. 在数百万次操作之后出现这个问题的原因是没有情况下地图有两个不同键的两个相似值,因为这在上下文中是不太可能的。

So at: 所以在:

25151l, 1.7583805400614032
24827l, 1.7583805400614032

it fails. 它失败。

Thanks for your help! 谢谢你的帮助!

I just executed the code, this case did return true to me. 我只是执行的代码,这种情况下也返回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));
        }     

Can you please give us the data that you input in the TreeMap. 你能告诉我们你在TreeMap中输入的数据吗? Thanks 谢谢

This is the containKey(Object key) implementation from JavaDocs 这是JavaDocs的containsKey(Object key)实现

containsKey 中的containsKey

boolean containsKey(Object key) boolean containsKey(Object key)

Returns true if this map contains a mapping for the specified key. 如果此映射包含指定键的映射,则返回true。

More formally, returns true if and only if this map contains a mapping for a key k such that, (key==null ? k==null : key.equals(k)) . 更正式地说,当且仅当此映射包含键k的映射时才返回true, (key == null?k == null:key.equals(k)) (There can be at most one such mapping.) (最多可以有一个这样的映射。)

Parameters: 参数:

 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 

Hope that helps. 希望有所帮助。

您必须对支持entrySet()/Map.Entry进行更改,从而更改键顺序,从而使搜索失败containsKey Key。

Most of these implementation classes rely on both hashCode() and equals() being supported and correct. 大多数这些实现类都依赖于hashCode()和equals()支持和正确。

If you truly have same hashcode from objects, try match equality. 如果您确实从对象获得相同的哈希码,请尝试匹配相等。 The answer suggested by me is that they do not match. 我建议的答案是他们不匹配。

Otherwise, the scenario ought to be small enough for you to publish the objects and/or their respective hashcode and equals method. 否则,该场景应该足够小,以便您发布对象和/或它们各自的哈希码和等于方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM