有关哈希码的问题

时间:2012-08-20 12:04:56

标签: java hashcode

我对equals和hashcode有些怀疑。我之前已经理解的是,如果该类应该添加到集合类或Map类中,我们需要覆盖对象类中的hashcode()和equals()方法。请参阅以下示例。我没有覆盖hashcode和equals方法。我仍然能得到想要的结果。有一点我明白,如果我想比较两个对象,我们需要覆盖equals方法。但是在这个例子中我不是比较两个对象,而是将对象添加到集合或Map而不覆盖hashcode和equals。任何人都可以解释为什么我们需要覆盖哈希码以及什么时候?

package equalshashcode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EqualsAndHashCode {
    public static void main(String[] args) {
        Student student1 = new Student("A");
        Student student2 = new Student("B");

        List<Student> studentList = new ArrayList<Student>();

        Map<Integer,Student> studentMap = new HashMap<Integer,Student>();

        studentMap.put(1, student1);
        studentMap.put(2, student2);

        studentList.add(student1);
        studentList.add(student2);

        System.out.println("Student HashMap:: "+studentMap.get(1));
        System.out.println("Before removing::"+studentList);
        System.out.println(studentList.remove(student1));//true success
        System.out.println("After removing::"+studentList);
    }
}

class Student{

    String name;
    public Student(String pName){
        this.name = pName ;
    }

    public String getName(){
        return this.name ;
    }
}

3 个答案:

答案 0 :(得分:4)

您并不总是需要实施equals()hashCode()来将元素添加到集合中。

对于List(例如您studentListArrayList实例),对大多数操作都无关紧要。

需要 equals()hashCode()的唯一地方是对象的“相等”。即使在那些地方,默认实施甚至可能就足够了。

在几种情况下,平等很重要,例如:

  • Set不能包含两个彼此相等的对象
  • Map密钥必须具有可检索的正确equals()实现(并且基于具体的Map实现,这可能意味着{ {1}}必须正确实施。)
  • “普通”hashCode()上的某些方法也需要相等。例如,Listcontains()indexOf()需要正确实施remove(Object) / equals()

答案 1 :(得分:1)

自定义equalshashCode方法通常用于确定实际的相等性。如果依赖于默认的equals方法,这将在内存中查找相同的实例。例如,如果没有自定义customObj1.equals(customObj2)方法,则equals将返回false,并且这两个对象是分开的(但在其他方面相同)实例。自定义equals方法的想法是使相同的示例在它们实际上相等时返回true。然后,Map将能够使用它来匹配get(key)请求中传递的密钥对象,以查找值,而无需拥有密钥的正确实例(HashMap实际使用hashCode这样做。)

这个最有用的例子是String s,这样你就可以myMap.get("key")得到正确的值,即使你的密钥实例与存储的密钥实例不一样在MapString实施equalshashCode为你)。一般情况下,我建议使用这些Java内置equalshashCode方法来构建自己的方法。例如,如果您的对象具有自然ID,例如说userName,则您的equals可以使用此String版本来完成您自己的等号(您显然可以比较多个字段):

public boolean equals(Object o) {
    if (o instanceof MyObj) {
        return userName.equals(((MyObj) o).userName));
    }
    return false;
}

因此,如果您只使用单个Thread或其他有限的变量,您可能永远不需要实现这些方法,但有时候知道这些方法是值得的。

答案 2 :(得分:0)

集合类可以很好地与具有默认equals / hashCode实现的对象一起工作 - 由于这个原因,不需要添加自己的。

自定义equals / hashCode方法很容易出错,除非你有充分的理由自己动手,否则你应该坚持使用java.lang.Object免费获得的那些。

创建自己的这些方法版本的最常见原因是,如果要将同一个类的两个单独实例视为相等。例如,如果您有一个Account类,并且您希望两个具有相同accountNumber属性的Account实例被视为相等,因为它们代表相同的真实帐户。在这种情况下,您可以将equals方法基于accountNumber的值,并且由于您现在拥有自定义equals方法,因此您需要提供一个合适的hashCode实现,以便实现equals/hashCode contract