2

我对equals和hashcode有一些疑问。我之前的理解是,如果该类应该添加到集合类或 Map 类中,我们需要覆盖对象类中的 hashcode() 和 equals() 方法。请看下面的例子。我没有覆盖 hashcode 和 equals 方法。我仍然得到了我想要的结果。我明白一件事,如果我想比较两个对象,我们需要重写 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 ;
    }
}
4

3 回答 3

4

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

对于 a List(例如 you studentList,它是一个ArrayList实例),大多数操作都无关紧要。

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

在某些情况下,平等很重要,例如:

  • ASet不能包含两个相等的对象
  • a的密钥Map必须具有正确的equals()实现才能被检索(并且基于具体的Map实现,这可能意味着hashCode()也必须正确实现)。
  • “正常”上的某些方法List也需要相等。例如contains(),需要正确执行indexOf()/remove(Object)equals()hashCode()
于 2012-08-20T12:09:43.393 回答
1

自定义equalshashCode方法通常用于确定实际相等性。如果您依赖默认equals方法,这将在内存中查找相同的实例。例如customObj1.equals(customObj2),如果没有自定义equals方法并且两个对象是单独的(但在其他方面相等)实例,则将返回 false。自定义方法的想法equals是,如果它们实际上相等,则使相同的示例返回 true。然后, AMap将能够使用它来匹配get(key)请求中传递的键对象以查找值,而无需具有正确的键实例(aHashMap实际用于hashCode执行此操作)。

最明显的例子是 for Strings,这样您就可以执行myMap.get("key")并获得正确的值,即使您的密钥实例与存储在Map( StringimplementsequalshashCodefor you) 中的密钥实例不同。一般来说,我会推荐使用这些 Java 内置equalshashCode方法来构建自己的。例如,如果您的对象具有自然 ID,例如 say userName,您equals可以使用Stringthis 的版​​本来完成您自己的 equals (您显然可以比较多个字段):

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

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

于 2012-08-20T12:23:10.443 回答
0

集合类将与具有默认 equals/hashCode 实现的对象完美配合 - 因此无需添加您自己的。

自定义的 equals/hashCode 方法很容易出错,除非您有充分的理由自行开发,否则您应该坚持使用通过 java.lang.Object 免费获得的方法。

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

于 2012-08-20T12:10:07.377 回答