我有一个对象的列表,在我们的例子中被称为规则,这个对象本身是一个字段列表,我必须对其进行哈希码比较,因为我们不能在 系统。
即假设我有两个规则R1和R2,字段为A&乙
现在,如果A&的值R1中的B分别为7和2。
在R2中它分别是3和4然后我用来检查两面性的过程 系统中的规则是哈希码比较失败
我使用的方法是
for(Rule rule : rules){
changeableAttrCode=0;
fieldCounter=1;
attributes = rule.getAttributes();
for(RuleField ruleField : attributes){
changeableAttrCode = changeableAttrCode + (fieldCounter * ruleField.getValue().hashCode());
fieldCounter++;
}
parameters = rule.getParameters();
for(RuleField ruleField : parameters){
changeableAttrCode = changeableAttrCode + (fieldCounter * ruleField.getValue().hashCode());
fieldCounter++;
}
changeableAttrCodes.add(changeableAttrCode);
这里是changeableAttrCodes,我们存储所有规则的哈希码。
所以请告诉我更好的方法,以便将来不会出现这种问题,也可以看到系统中的规则错误。
提前致谢
答案 0 :(得分:5)
hashcode()
并不意味着用于检查是否相等。 return 42;
是hashcode()
完全有效的实现。为什么不在规则对象中覆盖equals()
(以及hashcode()
)并使用它来检查两个规则是否相等?您仍然可以使用哈希码来检查需要调查哪些对象,因为两个equal()
对象应始终具有相同的哈希码,但这是您可能需要或可能不需要的性能改进,具体取决于您的系统。 / p>
答案 1 :(得分:4)
hashCode
和equals
。equals
的实施必须比较其值。然后使用HashSet<Rule>
并询问if(mySet.contains(newRule))
HashSet + equals implementation 解决了哈希的非唯一性问题。它使用散列进行分类和速度,但最后使用等号来确保具有相同散列的两个规则是否相同。
关于哈希的更多信息:如果您想手动执行,请使用素数sudggestion,并查看字符串哈希码的JDK代码。如果你想做一个干净的实现尝试检索元素的哈希码,制作某种int数组并使用Arrays.hashCode(int [])来获取它们组合的哈希码。
答案 2 :(得分:3)
已更新您的哈希算法未产生良好的哈希值分布 - 它为(7,2)和(3,4)提供相同的值:
1 * 7 + 2 * 2 = 11
1 * 3 + 2 * 4 = 11
它也会为(11,0),(-1,6),...提供相同的值,并且可以基于您当前的算法轻松地组成无数个类似的等价类。
当然你无法避免碰撞 - 如果你有足够的实例,哈希冲突是不可避免的。但是,您应该尽量减少碰撞的机会。良好的散列算法努力在很宽的值范围内均匀地散布散列值。实现此目的的典型方法是为包含 n 独立字段的对象生成哈希值,作为 n -digit数字,其基数足以容纳不同的哈希值对于各个领域。
在您的情况下,您应该乘以素数常数,而不是乘以fieldCounter
。 31(这将是你的号码的基础)。并为结果添加另一个素数常数,例如17.这为您提供了更好的散列值。 (当然具体的基础取决于你的领域可以采用什么价值 - 我没有相关信息。)
此外,如果您实施hashCode
,强烈建议您实施equals
- 实际上,您应该使用后者来测试相等性。
以下是关于implementing hashCode
的文章。
答案 3 :(得分:2)
我不明白你在这里要做什么。对于大多数散列函数场景,碰撞是不可避免的,因为有更多的对象要哈希,而不是有可能的哈希值(这是一个鸽子原理)。
通常情况下,两个不同的对象可能具有相同的哈希值。您不能单独依赖哈希函数来消除重复项。
一些散列函数在最小化碰撞方面比其他散列函数更好,但它仍然是不可避免的。
也就是说,有一些简单的指导方针通常会提供足够好的哈希函数。 Joshua Bloch在他的“Effective Java 2nd Edition”一书中给出了以下内容:
int
的{{1}}变量中。result
哈希码int
:
c
,请计算boolean
(f ? 1 : 0)
,请计算byte, char, short, int
(int) f
,请计算long
(int) (f ^ (f >>> 32))
,请计算float
Float.floatToIntBits(f)
,请计算double
,然后对结果Double.doubleToLongBits(f)
进行哈希处理,如上所述。long
方法通过递归调用equals
来比较字段,则在该字段上递归调用equals
。如果字段的值为hashCode
,则返回0. null
方法之一。Arrays.hashCode
合并到c
中,如下所示:result
答案 4 :(得分:0)
我开始写道,你可以通过Perfect Hashing获得你想要的唯一方法。
但后来我想到你说你不能在系统中复制对象这一事实。
根据helios的发人深省的评论进行编辑:
您的解决方案取决于您写下“无法复制规则”时的含义。
如果你的意思是字面上你不能,保证只有一个具有特定值集的规则的实例,那么你的问题是微不足道的:你可以进行身份比较,在这种情况下你可以进行身份比较使用==。
另一方面,你的意思是不应该出于某种原因(性能),那么你的问题也很简单:只进行价值比较。
考虑到你定义问题的方式,在任何情况下都不应该考虑使用哈希码来代替相等。正如其他人所指出的那样,哈希码本质上会产生冲突(假平等),除非你去Perfect Hashing解决方案,但为什么你会在这种情况下?