equals()とhashcode()について
1、新しいStudent.JAvaは、3つのfieldと、対応するget、setメソッドを含む.
2、equals()メソッドを書き換えずにテストを行う.
このとき、実行結果はfalseです.
equalsメソッドを書き換えない場合は、親のequalsメソッドがデフォルトで使用されますが、親オブジェクトのequals()メソッドは次のようになります.
すなわち,Objectでequals比較を実行する場合,実際には2等号で比較され,実質的に比較された2つのオブジェクトが同一のオブジェクトであるか否かは,s 1とs 2がそれぞれnewで出てきた2つのオブジェクトであるため,2等号は成立しないため,出力結果はfalseである.
3.Studioでequals()メソッドを書き換える.
この時点でテストを行い、結果はtrueです.
4、equals()を書き換え、hashcode()を書き換えない
テストコード:
実行結果:
falsefalsetrue
5、equals()を書き換え、hashcode()を書き換える.
出力結果
truetruetrue
以上、equals()を書き換えるにはhashcode()を同時に書き換える必要があります.そうしないと、hashセットで予想と一致しない結果が発生します.
補足:1、Stringがequals()を直接使用して2つのStringオブジェクトの値が等しいかどうかを比較できるのは、Stringクラスでequals()メソッドが書き換えられているからです.
2、equals()が等しい2つのオブジェクトは、hashcode()も等しいことを保証しなければならない.そうしないとjavaのhash集合クラスに問題が発生する.
3、equals()が等しくない2つのオブジェクトは、hashcode()が等しい可能性があります(ハッシュ生成時に衝突によるもの).
4、HashMapではcontainsKey(Object obj)、get(Object obj)があり、mapに指定されたkeyが含まれているか否かを判断したり、keyに基づいてvalueをクエリした場合、keyが等しいか否かを判断するルールはhashcodeが等しく、equalsがtrueを返す.
hashmapクラスget(Object obj)実装の場合:
5、hashcodeは主にHashtable、HashMap、HashSet、LinkedHashMapなどのhash集合クラスのために存在し、hash集合クラスはより効率的な(ハッシュアルゴリズム)クエリーと記憶を行うことができる.
http://huangqiqing123.iteye.com/blog/1462404
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メソッドがデフォルトで使用されますが、親オブジェクトのequals()メソッドは次のようになります.
public boolean equals(Object obj) {
return (this == obj);
}
すなわち,Objectでequals比較を実行する場合,実際には2等号で比較され,実質的に比較された2つのオブジェクトが同一のオブジェクトであるか否かは,s 1とs 2がそれぞれnewで出てきた2つのオブジェクトであるため,2等号は成立しないため,出力結果はfalseである.
3.Studioで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));
}
}
実行結果:
falsefalsetrue
5、equals()を書き換え、hashcode()を書き換える.
@Override
public int hashCode() {
return this.id.hashcode();
}
出力結果
truetruetrue
以上、equals()を書き換えるにはhashcode()を同時に書き換える必要があります.そうしないと、hashセットで予想と一致しない結果が発生します.
補足:1、Stringがequals()を直接使用して2つの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;
}
2、equals()が等しい2つのオブジェクトは、hashcode()も等しいことを保証しなければならない.そうしないとjavaのhash集合クラスに問題が発生する.
3、equals()が等しくない2つのオブジェクトは、hashcode()が等しい可能性があります(ハッシュ生成時に衝突によるもの).
4、HashMapではcontainsKey(Object obj)、get(Object obj)があり、mapに指定されたkeyが含まれているか否かを判断したり、keyに基づいてvalueをクエリした場合、keyが等しいか否かを判断するルールはhashcodeが等しく、equalsがtrueを返す.
hashmapクラスget(Object obj)実装の場合:
public V get(Object paramObject)
{
if (paramObject == null)
return getForNullKey();
int i = hash(paramObject.hashCode());
for (Entry localEntry = this.table[indexFor(i, this.table.length)]; localEntry != null; localEntry = localEntry.next)
{
Object localObject;
if ((localEntry.hash == i) && (((localObject = localEntry.key) == paramObject) || (paramObject.equals(localObject))))
return localEntry.value;
}
return null;
}
5、hashcodeは主にHashtable、HashMap、HashSet、LinkedHashMapなどのhash集合クラスのために存在し、hash集合クラスはより効率的な(ハッシュアルゴリズム)クエリーと記憶を行うことができる.
http://huangqiqing123.iteye.com/blog/1462404