2014-10-20 24 views
1

我知道(约定),当equals被覆盖时,我们需要重写哈希码。 为什么我应该考虑用于等同比较的相同字段来计算哈希码? 是否通过避免将太多对象映射到同一个存储桶来提高性能? 即在同一个“日期”上创建的所有对象都会映射到相同的存储桶,并且使用equals()方法检查对象是否存在需要花费时间进行线性比较?重写哈希码时要考虑的数据成员,等于

如果我的上述说法属实,除了性能问题之外,下面的代码还会出现其他潜在问题。这是我们应该使用equals中的相同字段/成员来计算哈希码的唯一原因吗?请分享。谢谢。

class MyClass { 
    int date; 
    int pay; 
    int id; 

    public boolean equals(Object o) { 
    //null and same class instance check 
    MyClass obj = (MyClass) o; 
    return (date == obj.date && pay == obj.pay && id == obj.id); 
    } 

    public int hashCode() { 
    int hash = 7; 
    return (31 * hash + date); 
    } 
} 

//请原谅语法错误,我不使用ide键入。

***我的本意是用在平等的各个领域,并知道为什么要在哈希代码中使用相同数量的元素,如果只有少数元素被用来

澄清会发生什么: 由于只有使用“日期”计算哈希码,指针检查正确的桶地址(你同意吗?)此外,我得到该桶中的项目列表,集合将迭代检查特定的obj是否存在使用equals。而我对平等的定义是“所有领域必须相同”。有了这个,我相信我的代码工作正常,我只能找到性能问题。请指出我错在哪里。谢谢

回答

0

我在Effective Java中找到了Joshua Bloch在2nd edtn第49页的答案“不要试图从哈希码计算中排除重要部分以提高性能”。质量差可能会降低散列表的性能。

所以我的猜测是正确的,多个散列将映射到同一个桶。

其他信息: http://www.javaranch.com/journal/2002/10/equalhash.html

由于类成员/变量Num和数据不参加 等于方法相比,它们也应在 计算的哈希码的参与。 虽然这不是强制性的。您可以使用 比较中使用参与equals方法 比较的变量子集来提高hashCode方法的性能。性能 的hashCode方法确实非常重要。

+0

你还必须考虑这个要求(在同一本书中的其他地方提及,IIRC)'hashcode()'与** **一致。基本上,这意味着如果'obj1.equals(obj2)',那么'obj1'和'obj2' *必须具有相同的散列值。相反是不正确的。如果'!obj1.equals(obj2)'和它们*具有相同的散列值,那么它实际上并不是错误的,但是基于散列的集合将表现得很差。 – 2014-10-23 06:23:17

+0

@KevinKrumwiede,是的我意识到这一点,我的观点是要明白,如果代码失败的时候:如果'n'成员用于equals()比较,我使用'小于n'成员的散列码,我的代码会破坏还是一些东西。但它不会中断,但会增加将多个对象映射到同一个存储桶的机会,从而降低性能。谢谢。 – 2014-10-23 06:32:02

1

对于你的例子,我建议你只使用id为平等和注释,他们是覆盖。另外,我喜欢覆盖toString()

@Override 
public boolean equals(Object o) { 
    if (o instanceof MyClass) { 
    return (id == ((MyClass) o).id); 
    } 
    return false; 
} 

@Override 
public int hashCode() { 
    return id; 
} 

@Override 
public String toString() { 
    return String.format("MyClass (id=%d, date=%d, pay=%d)", id, date, pay); 
} 

这样,你可以更新date和/或pay无需重新创建哈希结构。此外,这似乎是独特的实例。

+0

我的意图是使用equals中的所有字段,并知道为什么应该在散列码中使用相同数量的元素,以及如果仅使用少量元素会发生什么/谢谢。 – 2014-10-20 02:44:58

+0

@DavidPrun是的,我读了你的代码。如果你使用所有的元素并且你的实例不是不可变的,那么改变一个字段将不会像你在'HashSet'或'HashMap'中期望的那样工作,因为你的实例会改变它们的相等性,并且hashCode的值将不匹配桶元素被分配给。 – 2014-10-20 02:47:04

+0

Elliott Frish,只使用“日期”计算哈希码,指针检查正确的桶地址(您是否同意?)此外,我得到该桶中的项目列表,集合将迭代检查特定的obj是否存在使用equals。而我对平等的定义是“所有领域必须相同”。有了这个,我相信我的代码有问题,我只能找到性能问题。请指出我错在哪里。谢谢。 – 2014-10-20 04:34:33