我对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 ;
}
}
答案 0 :(得分:4)
您并不总是需要实施equals()
和hashCode()
来将元素添加到集合中。
对于List
(例如您studentList
,ArrayList
实例),对大多数操作都无关紧要。
您需要 equals()
和hashCode()
的唯一地方是对象的“相等”。即使在那些地方,默认实施甚至可能就足够了。
在几种情况下,平等很重要,例如:
Set
不能包含两个彼此相等的对象Map
的密钥必须具有可检索的正确equals()
实现(并且基于具体的Map
实现,这可能意味着{ {1}}必须正确实施。)hashCode()
上的某些方法也需要相等。例如,List
,contains()
和indexOf()
需要正确实施remove(Object)
/ equals()
答案 1 :(得分:1)
自定义equals
和hashCode
方法通常用于确定实际的相等性。如果依赖于默认的equals
方法,这将在内存中查找相同的实例。例如,如果没有自定义customObj1.equals(customObj2)
方法,则equals
将返回false,并且这两个对象是分开的(但在其他方面相同)实例。自定义equals
方法的想法是使相同的示例在它们实际上相等时返回true。然后,Map
将能够使用它来匹配get(key)
请求中传递的密钥对象,以查找值,而无需拥有密钥的正确实例(HashMap
实际使用hashCode
这样做。)
这个最有用的例子是String
s,这样你就可以myMap.get("key")
得到正确的值,即使你的密钥实例与存储的密钥实例不一样在Map
(String
实施equals
和hashCode
为你)。一般情况下,我建议使用这些Java内置equals
和hashCode
方法来构建自己的方法。例如,如果您的对象具有自然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。