加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 恢复哈希码“sum”

发布时间:2020-12-15 04:41:00 所属栏目:Java 来源:网络整理
导读:所以,不是每次都计算哈希码,我想我可以保持一个更新所有更改的整数.想象一下有助于哈希码的属性的setter: public void setFoo(Foo newFoo){ this.hashCalculator.remove(this.foo.hashCode()); // remove old hash code this.hashCalculator.add(newFoo.has
所以,不是每次都计算哈希码,我想我可以保持一个更新所有更改的整数.想象一下有助于哈希码的属性的setter:

public void setFoo(Foo newFoo){
    this.hashCalculator.remove(this.foo.hashCode()); // remove old hash code
    this.hashCalculator.add(newFoo.hashCode()); // add new hash code
    this.foo = newFoo; // set new foo
}

(我希望我没有做一些愚蠢的事情)我认为这将是简单的数学,但我没有实现它.我认为它与溢出的整数有关,但我不确定.显然我错过了一些东西.该部门的剩余部分应该可以加回到价值中,对吧?

这是我的代码.结果应该是1,但这不是我得到的.

class HashCode
{
    public int value = 1;

    public void add(int val){
        // as suggested by effective java
        value = value * 37 + val;
    }

    public void remove(int val){
        value = (value - val) / 37;
    }
}

HashCode o = new HashCode();

for(int a = 0; a < 1000; a++){
    o.add(a);
}

for(int r = 0; r < 1000; r++){
    o.remove(r);
}

System.out.println(o.value); // should be 1

解决方法

第一:无法正确反转导致整数溢出的操作.基本上问题是您无法知道整数溢出是否在前一个操作中发生过一次,两次甚至更多次.因此,在最后一次哈希计算之前,您无法获得原始值.

第二:哈希计算取决于应用的哈希值的顺序.

((1 * 37 + 0) * 37 + 1) * 37 + 2 = 50692
((1 * 37 + 2) * 37 + 1) * 37 + 0 = 53428
           ^         ^         ^ the hash values.

由于附加最后一个值的哈希值更改取决于所有先前的哈希值,您不能只更改一个中间哈希值,因此没有(表现良好)方法来消除前一个示例中的1对所有未来计算的影响.

如果您使用1,2,3等测试循环而不是1000开始,这应该是显而易见的.如果没有整数溢出,只有在按照添加它们的相反顺序删除哈希值时,循环才会起作用.这是一种在“现实生活”中应用没有意义的限制. @JB Nizet在his comment写的内容在我看来是正确的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读