可能之前已经问过这个问题(我没有找到它)......
我有java.util.Set
aprox。 50000字符串。我想生成某种哈希来检查它是否已被更改(比较Set的两个版本的哈希值)?
如果Set更改,则散列必须不同。
如何实现?谢谢!
修改
对于那种误导性的措辞感到抱歉。我不想检查“它”是否已被更改(相同的实例)。相反,我想检查两个数据库查询,它们生成两个 - 可能是相同的 - 一组字符串的实例是相等的。
答案 0 :(得分:4)
我尝试使用java.util.AbstractSet
的{{1}}方法,如文档中所述:
返回此set的哈希码值。一组的哈希码是 定义为集合中元素的哈希码的总和, 其中null元素的哈希码被定义为零。这个 确保s1.equals(s2)暗示s1.hashCode()== s2.hashCode() 对于任何两套s1和s2,按照一般合同的要求 是Object.hashCode()。
当然,这仅适用于hashCode
实施范围从Set
延伸的情况,我想您使用例如AbstractSet
。 一如既往存在哈希冲突的可能性。
或者,您可以扩展现有的java.util.HashSet
实现并覆盖状态更改方法,如果每个对象的哈希计算变得过于昂贵,这可能是有意义的,例如:
Set
答案 1 :(得分:3)
基于此声明:
If the Set changes, the hash has to be different
除非你有更多限制,否则实际上无法实现。通常,散列是某个固定空间中的值。例如,您的哈希可能是32位整数,因此有2 ^ 32个可能的哈希值。通常,b位可以获得2 ^ b个可能的哈希值。为了达到你想要的效果,你必须确保每一个可能的集合(即 - 所有集合的集合!)小于或等于2 ^ b。但我的猜测是你可以拥有任意字符串,所以这是不可能的。即使有可能,您也必须想出一种映射到哈希空间的方法,这可能具有挑战性。
但是,使用良好的散列函数,更改集合最终不会产生相同的散列值。因此,您可以使用散列来确定不等式,但如果散列相同,则仍需要检查是否相等。 (这与哈希集或哈希映射背后的想法相同,其中元素基于哈希码映射到存储桶,但您必须检查相等性。)
类似于Paul所提到但不同的:您可以改为创建具有版本号的集合实现,并确保在集合发生变化时始终生成新的版本号。那你可以比较版本号吗?我不确定你是否关心不可变集或者是否可变集更改回你看过的版本(即 - 它应该总是得到相同的版本)。
希望这有帮助。
答案 2 :(得分:3)
如果你需要提高hashCode的性能(因为它对于大型Set来说相当昂贵),你可以缓存它并随时更新它。
class MyHashSet<E> extends LinkedHashSet<E> {
int hashCode = 0;
@Override
public boolean add(E e) {
if (super.add(e)) {
hashCode ^= e.hashCode();
return true;
}
return false;
}
@Override
public boolean remove(Object o) {
if(super.remove(o)) {
hashCode ^= o.hashCode();
return true;
}
return false;
}
@Override
public void clear() {
super.clear();
hashCode = 0;
}
@Override
public int hashCode() {
return hashCode;
}
}
答案 3 :(得分:2)
有时候更简单更好。我建议您编写自己的Set
实现。在其中,覆盖add
和remove
方法,以便在Set
被修改时设置标记。为标志isModified
添加一个getter,您不必担心哈希开销或冲突。只需致电MyCustomSet.isModified
。
或者,您可以致电Collections.unmodifiableSet
以获取无法修改的Set
周围的包装。如果代码尝试修改集合,则抛出异常。