如何生成一组哈希以确保完整性?

时间:2012-01-04 07:45:16

标签: java hash set

可能之前已经问过这个问题(我没有找到它)......

我有java.util.Set aprox。 50000字符串。我想生成某种哈希来检查它是否已被更改(比较Set的两个版本的哈希值)?

如果Set更改,则散列必须不同。

如何实现?谢谢!

修改
对于那种误导性的措辞感到抱歉。我不想检查“它”是否已被更改(相同的实例)。相反,我想检查两个数据库查询,它们生成两个 - 可能是相同的 - 一组字符串的实例是相等的。

4 个答案:

答案 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实现。在其中,覆盖addremove方法,以便在Set被修改时设置标记。为标志isModified添加一个getter,您不必担心哈希开销或冲突。只需致电MyCustomSet.isModified

或者,您可以致电Collections.unmodifiableSet以获取无法修改的Set周围的包装。如果代码尝试修改集合,则抛出异常。