我有两个不同 Map
,但是它们具有相同的哈希码值:
Map<String,Boolean> map1=new HashMap<>();
map1.put("a", false);
map1.put("b", true);
map1.put("c", true);
map1.put("d", true);
map1.put("e", true);
map1.put("f", false);
map1.put("g", true);
map1.put("k", false);
Map<String,Boolean> map2=new HashMap<>();
map2.put("a", false);
map2.put("b", false);
map2.put("c", false);
map2.put("d", false);
map2.put("e", true);
map2.put("f", true);
map2.put("g", false);
map2.put("k", true);
System.out.println(map1.hashCode()); //9595
System.out.println(map2.hashCode()); //9595 --> should be different as the values are different!
hashcode
函数的行为对我来说非常好:如果映射发生变化,那么哈希码当然应该发生变化。如果映射中的值相同,则哈希码应相同。但是,标准哈希显然会导致相似对象的冲突。 如何为这两个地图计算哈希?
我尝试从org.apache.commons
使用HashCodeBuilder
System.out.println(new HashCodeBuilder(17, 31)
.append(map1.values())
.toHashCode());
System.out.println(new HashCodeBuilder(17, 31)
.append(map2.values())
.toHashCode());
System.out.println(new HashCodeBuilder(17, 31)
.append(map4.values()) //identical values as map2
.toHashCode());
哪个返回给map1,map2和map4(具有相同的值als map2)一个不同的哈希值。但是,具有相同值的地图的哈希值应该相同。...
哈希码功能的行为对我来说是很好的:如果映射改变了,那么哈希码当然也应该改变。
强调应更改,不是必须的。关于hashCode
的唯一要求是,如果值相等,则哈希必须相等。它的确<< not >>给出了有关值不同时应发生的任何要求。它建议散列应该不同,但这只是一个建议,在实践中hashCode
不能遵循该建议的情况很多。您的方法有缺陷。您不得对不同值的散列做任何假设,尤其是不要假设它们是不同的。
例如,如果您有哈希冲突,例如在基于哈希的集合中,则必须使用equals
作为第二步,以检查它实际上是同一元素还是两个不同元素的冲突。
从documentation的Object#hashCode
开始:
这是不需要
,如果根据equals(java.lang.Object)
方法两个对象为不等于,则在两个对象中的每个对象上调用hashCode
方法必须产生不同的整数结果。但是,程序员应该意识到,为哈希表的不相等对象可能会提高性能产生明显的整数结果。
当然有一个技术原因。散列是关于用很小的东西表示可能很大的东西。
在这种情况下,用单个Object
表示任何int
。只有2^32
个不同的整数值,但是有无数个不同的Map
设置。因此,不可能为每个变量都使用不同的int
哈希。
Wikipedia#Hash function上有关此主题的更多信息。