hashcodeとequalsに対する深い理解
3028 ワード
hashcodeとequalsに対する深い理解
---の一例
---hashcodeとequalsメソッドが書き換えられていない場合
System.out.println(s1.equals(s2));//false
2つのオブジェクトが生成されたためfalseが印刷され、Objectのequalsメソッドが呼び出され、デフォルトでは2つのオブジェクトのアドレスが同じかどうかが直接比較されます.
---equalsメソッドのみを書き換える(eclipse生成)
現在、idが同じと考えられているビジネスロジックがあり、同じ学生と考えられているため、equalsメソッドが追加されました.以下のようにします.
System.out.println(s1.equals(s2));//true
今また需要があって、生成した学生をsetの中に入れます
Set set = new HashSet();
set.add(s1);
set.add(s2);
System.out.println(set.size());//2
System.out.println(s1.hashCode() == s2.hashCode());//false
s 1とs 2 idが同じである以上equalsは等しくなったが,結果は2であり,setが重複オブジェクトに入れられないことを知るにはhashcodeを書き直してもう一度試してみる.
---hashcodeメソッドの書き換え(eclipse生成)
---』結論
*ビジネスロジックでオブジェクトが同じオブジェクトであることを再定義する場合は、両方のメソッドを同時に書き換える必要があります.
*objectクラスではhashcode()メソッドはローカルメソッドであり、オブジェクトのアドレス値を返します.objectクラスのequals()メソッドも2つのオブジェクトのアドレス値を比較します.
*equalsが等しいとhashcode()が等しく、hashcode()が等しく、equalsが必ずしも等しくない.
*equalsメソッドは書かれておらず、呼び出すとObjectのequalsメソッドが呼び出されます.デフォルトでは、2つのオブジェクトのアドレスが同じかどうかを直接比較します.つまりthis==objです.
*HashMapまたはHashSetを使用する場合、その内容をメモリアドレスで比較するのではなく「重複するかどうか」の基準とする場合は、この2つの方法を自分で書き換える必要があります.
*HashMapまたはHashSetの比較プロセス:まずhash値に基づいてある領域に位置決めし、その後領域内でequals判断を行い、効率が高い.
*hashCodeの演算にオブジェクトの属性値が関与している場合、削除する際にその属性値を変更することはできません.そうしないと深刻なメモリリークの問題が発生するため、オブジェクトの同じ属性を使用してhashCode()とequals()の2つのメソッドを生成することをできるだけ保証します.
参照先:
http://blog.csdn.net/whuslei/article/details/6686612
http://blog.csdn.net/jiangwei0910410003/article/details/22739953
http://blog.csdn.net/steveguoshao/article/details/12576849
http://stackoverflow.com/questions/3613102/why-use-a-prime-number-in-hashcode
---の一例
public class Student
{
private int id;
private String name;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public static void main(String[] args)
{
Student s1 = new Student();
s1.setId(1);
Student s2 = new Student();
s2.setId(1);
System.out.println(s1.equals(s2)); //false
}
}
---hashcodeとequalsメソッドが書き換えられていない場合
System.out.println(s1.equals(s2));//false
2つのオブジェクトが生成されたためfalseが印刷され、Objectのequalsメソッドが呼び出され、デフォルトでは2つのオブジェクトのアドレスが同じかどうかが直接比較されます.
---equalsメソッドのみを書き換える(eclipse生成)
現在、idが同じと考えられているビジネスロジックがあり、同じ学生と考えられているため、equalsメソッドが追加されました.以下のようにします.
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Student other = (Student) obj;
if (id != other.id) return false;
return true;
}
System.out.println(s1.equals(s2));//true
今また需要があって、生成した学生をsetの中に入れます
Set
set.add(s1);
set.add(s2);
System.out.println(set.size());//2
System.out.println(s1.hashCode() == s2.hashCode());//false
s 1とs 2 idが同じである以上equalsは等しくなったが,結果は2であり,setが重複オブジェクトに入れられないことを知るにはhashcodeを書き直してもう一度試してみる.
---hashcodeメソッドの書き換え(eclipse生成)
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
System.out.println(set.size());//1
System.out.println(s1.hashCode() == s2.hashCode());//true
---』結論
*ビジネスロジックでオブジェクトが同じオブジェクトであることを再定義する場合は、両方のメソッドを同時に書き換える必要があります.
*objectクラスではhashcode()メソッドはローカルメソッドであり、オブジェクトのアドレス値を返します.objectクラスのequals()メソッドも2つのオブジェクトのアドレス値を比較します.
*equalsが等しいとhashcode()が等しく、hashcode()が等しく、equalsが必ずしも等しくない.
*equalsメソッドは書かれておらず、呼び出すとObjectのequalsメソッドが呼び出されます.デフォルトでは、2つのオブジェクトのアドレスが同じかどうかを直接比較します.つまりthis==objです.
*HashMapまたはHashSetを使用する場合、その内容をメモリアドレスで比較するのではなく「重複するかどうか」の基準とする場合は、この2つの方法を自分で書き換える必要があります.
*HashMapまたはHashSetの比較プロセス:まずhash値に基づいてある領域に位置決めし、その後領域内でequals判断を行い、効率が高い.
*hashCodeの演算にオブジェクトの属性値が関与している場合、削除する際にその属性値を変更することはできません.そうしないと深刻なメモリリークの問題が発生するため、オブジェクトの同じ属性を使用してhashCode()とequals()の2つのメソッドを生成することをできるだけ保証します.
参照先:
http://blog.csdn.net/whuslei/article/details/6686612
http://blog.csdn.net/jiangwei0910410003/article/details/22739953
http://blog.csdn.net/steveguoshao/article/details/12576849
http://stackoverflow.com/questions/3613102/why-use-a-prime-number-in-hashcode