所以,不是每次都计算哈希码,我想我可以保持一个更新所有更改的整数.想象一下有助于哈希码的属性的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写的内容在我看来是正确的.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。