java哈希表包含怪异

时间:2012-03-22 21:27:47

标签: java equals hashcode

在什么情况下,如果正确实现了hashCode和equals(),下面的代码会返回false吗?

myLinkedHashMap.containsKey(myLinkedHashMap.keySet().iterator().next())

7 个答案:

答案 0 :(得分:7)

尽管hashCode是“确定性的”,但我可以想到的最可能的情况是,它可能基于可变字段。如果您在将hashCode放入Map之后更改用于计算{{1}}的字段,那么您将无法再找到它。

编辑:应该澄清你'通常'将无法再找到它。偶尔它仍然可以工作,因为两个数字仍然可以重新进入相​​同的存储桶。当然,这只会在发生这种情况时增加混乱!

答案 1 :(得分:3)

我看到的每个哈希算法都是“确定性的”,因为对于给定的一组输入值,你得到相同的哈希值。

如果基于对象的可变属性计算哈希码,则哈希码将在哈希映射中更改后,如果任何可变属性发生更改。

答案 2 :(得分:2)

目前尚不清楚“确定性”是什么意思,但是在将密钥插入哈希映射后,对密钥的任何哈希变化突变很容易产生这种影响。

import java.util.*;

public class Test {
  public static void main(String[] args) {
    List<String> strings = new ArrayList<String>();
    Map<List<String>, String> map = new LinkedHashMap<List<String>, String>();

    map.put(strings, "");
    System.out.println(map.containsKey(map.keySet().iterator().next())); // true
    strings.add("Foo");
    System.out.println(map.containsKey(map.keySet().iterator().next())); // false
  }
}

ArrayList<T>的哈希码是确定性的,但这并不意味着如果列表内容发生变化,它就不会改变。

答案 3 :(得分:2)

  1. 如果hashCode()基于可变的实例属性,并且在插入后更改了这些属性,则迭代期间的hashCode()调用将返回某些内容不同。 equals()应基于这些相同的属性,预计也会失败。

  2. 当另一个帖子在迭代过程中从Map删除了所有下一个项时,将不再有next()

  3. 我不会使用hashCode()值作为键,我希望你自己使用对象。

答案 4 :(得分:1)

如果您的hashCodeequals彼此不一致,则可能会返回false。例如,如果equals方法始终返回false,则返回false,因为没有任何对象可以比较等于地图中的键。

希望这有帮助!

答案 5 :(得分:0)

您可能希望先检查hasNext()。

答案 6 :(得分:0)

您可以在获取第一个密钥和调用containsKey之间删除另一个线程中的第一个密钥。