关于equals()跟hashcode()方法的一些实验
关于equals()和hashcode()方法的一些实验
1、新建一Student.java,包含3个field,和相应的get、set方法。
package t; public class Student{ private String id; private String name; private int age; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
2、不重写equals()方法,进行测试。
package t; public class Test2 { public static void main(String[] args){ Student s1 = new Student(); s1.setId("001"); Student s2 = new Student(); s2.setId("001"); System.out.println(s1.equals(s2)); } }
此时,执行结果是false。
如果不重写equals方法,将默认使用父类的equals方法进行比较,而父类Object的equals()方法如下:
public boolean equals(Object obj) { return (this == obj); }
即,在Object中执行equals比较时,实际上是用双等号进行比较的,实质上比较的两个对象是否同一个对象,由于s1和s2是分别new出来的2个对象,所以,双等号是不成立的,故而输出结果是false。
3、在Student中重写equals()方法。
@Override public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof Student) { Student anotherStudent = (Student)anObject; //只要2个学生的学生编号相同,则认为2个对象相同。 return this.getId().equals(anotherStudent.getId()); } return false; }
此时再行测试,结果是true。
4、重写equals(),不重写hashcode()
测试代码:
package t; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class Test2 { public static void main(String[] args){ Student s1 = new Student(); s1.setId("001"); Student s2 = new Student(); s2.setId("001"); //关于HashSet的测试 Set<Student> set = new HashSet<Student>(); set.add(s1); System.out.println(set.contains(s2)); //关于HashMap的测试 Map<Student, Student> map = new HashMap<Student, Student>(); map.put(s1, s1); System.out.println(map.containsKey(s2)); System.out.println(map.containsValue(s2)); } }
执行结果:
false
false
true
5、重写equals(),并且重写hashcode()。
@Override public int hashCode() { return 1; }
输出结果
true
true
true
综上,重写equals()一定要同时重写hashcode(),否则在hash集合中,会出现与预期不一致的结果。
补充说明:String之所以可以直接使用equals()比较两个String对象的值是否相等,是因为在String类中已经对equals()方法进行了重写。
/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*
* @param anObject
* The object to compare this {@code String} against
*
* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
http://huangqiqing123.iteye.com/blog/1462404