hashCode()とequals()の本質的な違いと連絡を詳しく説明します。
javaを学んで、ビデオによって実例の過程をします中で、equalsとhashcodeの2つの方法に対して少し深いことを理解して、主にそれらの2つがとても混淆しやすくて、間違いやすくて、自分でまたネット上の資料を通じて学んで、みんなと分かち合います。
equals()メソッド
equalsはObjectクラスが提供する方法の一つであり、周知のように、各javaクラスはObjectクラスから継承されているので、どのオブジェクトにもequalsという方法がある。私達はこの方法を使う時普通はすべてこの方法を書き直して、why?
まずObjectクラスのequals()方法のソースコードを見ます。
もちろんこれからはequalsの方法を書き換えます。共通の約束を守らなければなりません。java.lang.Objectからの規範で、equals方法は等価関係を実現しました。以下は要求に従う5点です。
1.自発性:任意の参照値xに対して、x.equals(x)は必ずtrueである。
2.対称性:任意の参照値xとyに対して、x.equals(y)がtrueに戻ると、y.equals(x)も必ずtrueに戻ります。
3.伝達性:任意の参照値x、y、zに対して、x.equals(y)がtrueに戻り、y.equals(z)もtrueに戻ります。x.equals(z)も必ずtrueに戻ります。
4.整合性:任意の参照値xとyに対して、equals比較のためのオブジェクト情報が修正されていない場合、何度もx.equals(y)を呼び出しても、一致してtrueに戻るか、またはfalseに戻る。
5.非空性:任意の非空引用値xに対して、x.equals(null)はfalseに返される。
hashCodeの方法
hashcode()この方法もobject類から継承されたもので、object類では次のように定義されています。
equals方法を書き換えたクラスごとに、hashCode方法を書き換えなければなりません。そうしないと、Object.hashCodeの共通約束に違反してしまい、このクラスはハッシュ値に基づくすべてのグループと結合できなくなります。
hashCode()の戻り値とequals()の関係は以下の通りです。
x.equals(y)が「true」に戻るなら、xとyのhashCode()は等しくしなければならない。
x.equals(y)がfalseに戻るなら、xとyのhashCode()が等しいかもしれません。
equals()は、2つのSetが等しいかどうかを判定することである。参照値が同じオブジェクトを指すかどうかを決定します。
1、セットセットセットセットにオブジェクトを追加する場合は、まず、オブジェクトを追加するhashCodeコードを計算し、その値に基づいて現在のオブジェクトを格納し、その位置にオブジェクトが一つも存在しない場合は、セットセットセットにはオブジェクトが存在しないと判断し、直接に追加します。この位置にオブジェクトがある場合、次にそのセットに追加されたオブジェクトとその位置に追加されたオブジェクトとのequals方法の比較を行い、もしこのequals方法がfalseに戻ると、集合中にそのオブジェクトが存在しないと考えて、もう一度ハッシュを行い、そのオブジェクトをハッシュ後に算出された新しいアドレスに置くと、equals方法がtrueに戻ると、集合は、集合の中に既にオブジェクトが存在していると考えられ、そのオブジェクトを集合に追加することはない。
2、equals方法を書き換えるときは、hashCode方法を書き換えなければなりません。javaのセットでは、2つのオブジェクトが等しいかどうかを判断するルールは、
1)二つの対象のhashCodeが等しいかどうかを判断する。
もし等しくないならば、2つの対象も等しくないと思って、終わります。等しい場合は、2に移動します。
2)両オブジェクトがequalsで演算されているかどうかを判断する。
同じでないと、二つのオブジェクトも同じではないと思います。
等しい場合、2つのオブジェクトが等しいかどうかを判断する鍵となる。
hashcode()が等しい場合、equals()の方法も異なることがあります。
しかし、次の手順を見てください。
これはhashsetの原則と違反していますか?回答:hashcodeによってnewStudent(1,「zhangsan」)オブジェクトを2回作成した場合、生成されたのは異なるハッシュコード値であるため、hashsetは彼を異なる対象として扱ったので、当然この時のequals()方法で返した値も違いません。なぜ、異なるハッシュ・コード値が生成されるのか?なぜかというと、私たち自身が書いたStudent類は、自分のhashcode()とequals()をやり直す方法がないからです。
したがって、比較時には、継承されたobjectクラスのhashcode()方法であり、比較は対象のアドレス(参照アドレス)であり、new法を用いてオブジェクトを作成し、2回生成されたのはもちろん別のオブジェクトです。結果としては、2つのオブジェクトのhashcode()の戻り値が違います。この問題はどう解決しますか?
理由は、Studentクラスで、shcode()とequals()の方法を見直すためです。
締め括りをつける
この知識は間違いやすいです。理解は深くしなければなりません。多くの実践は原理と定義に対してより深く理解します。何か問題があったらいつでもメッセージを残してください。みなさんの応援に感謝します。
equals()メソッド
equalsはObjectクラスが提供する方法の一つであり、周知のように、各javaクラスはObjectクラスから継承されているので、どのオブジェクトにもequalsという方法がある。私達はこの方法を使う時普通はすべてこの方法を書き直して、why?
まずObjectクラスのequals()方法のソースコードを見ます。
public boolean equals(Object obj) {
return (this == obj);
}
この方法から、一例がそれ自体に等しい場合にのみ、equals()はtrue値を返していることが分かる。一般的には、この時点で比較されるのは、2つの参照がメモリ内の同じオブジェクトを指すかどうかであり、インスタンスが等しいかどうかを称することもできる。私たちはequals()を使って、二つの指向性オブジェクトの参照を比較する時、それらが同じオブジェクトを指すかどうかではなく、論理的には等しいかどうかを知りたいです。つまり、この方法を書き換える理由です。
Strings1 = new String(“kvill”),String s2 = new String(“kvill”);s1.equals(s2) ture,
Stringクラスで既にequals()方法が書き換えられていることを説明し、equals()方法を書き換えないとs 1.equals(s 2)デフォルトでは、2つのオブジェクトが指すメモリアドレスが同じかどうかを比較し、戻り値は必ずfalseとなる。もちろんこれからはequalsの方法を書き換えます。共通の約束を守らなければなりません。java.lang.Objectからの規範で、equals方法は等価関係を実現しました。以下は要求に従う5点です。
1.自発性:任意の参照値xに対して、x.equals(x)は必ずtrueである。
2.対称性:任意の参照値xとyに対して、x.equals(y)がtrueに戻ると、y.equals(x)も必ずtrueに戻ります。
3.伝達性:任意の参照値x、y、zに対して、x.equals(y)がtrueに戻り、y.equals(z)もtrueに戻ります。x.equals(z)も必ずtrueに戻ります。
4.整合性:任意の参照値xとyに対して、equals比較のためのオブジェクト情報が修正されていない場合、何度もx.equals(y)を呼び出しても、一致してtrueに戻るか、またはfalseに戻る。
5.非空性:任意の非空引用値xに対して、x.equals(null)はfalseに返される。
hashCodeの方法
hashcode()この方法もobject類から継承されたもので、object類では次のように定義されています。
public native int hashCode();
hashCodeは、典型的にはオブジェクトの内部アドレスから変換された整数であるオブジェクトのハッシュコード値を返し、その実装は主に、ハッシュテーブル(例えば、java.util.Hashtableが提供するハッシュテーブル)の性能を向上させるためである。equals方法を書き換えたクラスごとに、hashCode方法を書き換えなければなりません。そうしないと、Object.hashCodeの共通約束に違反してしまい、このクラスはハッシュ値に基づくすべてのグループと結合できなくなります。
hashCode()の戻り値とequals()の関係は以下の通りです。
x.equals(y)が「true」に戻るなら、xとyのhashCode()は等しくしなければならない。
x.equals(y)がfalseに戻るなら、xとyのhashCode()が等しいかもしれません。
public class TestEquals {
public static void main(String args[]) {
Student s1 = new Student(" ", 6);
Student s2 = new Student(" ", 6);
if (s1.equals(s2)) {
System.out.println(" s1 :" + s1.hashCode() + " s2 :"
+ s2.hashCode());
} else {
System.out.println(" ");
}
}
}
class Student {
private int age;
private String name;
public Student() {
}
public Student(String name, int age) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int hashCode() {
return (this.name.hashCode() + this.age) * 31;
}
public boolean equals(Object obj) {
boolean result = false;
if (obj == null) {
result = false;
}
if (this == obj) {
result = true;
}
if (obj instanceof Student) {
Student stu = (Student) obj;
if (stu.getName().equals(this.name) && stu.getAge() == (this.age)) {
result = true;
}
} else {
result = false;
}
return result;
}
}
詳細に分析するequals()は、2つのSetが等しいかどうかを判定することである。参照値が同じオブジェクトを指すかどうかを決定します。
1、セットセットセットセットにオブジェクトを追加する場合は、まず、オブジェクトを追加するhashCodeコードを計算し、その値に基づいて現在のオブジェクトを格納し、その位置にオブジェクトが一つも存在しない場合は、セットセットセットにはオブジェクトが存在しないと判断し、直接に追加します。この位置にオブジェクトがある場合、次にそのセットに追加されたオブジェクトとその位置に追加されたオブジェクトとのequals方法の比較を行い、もしこのequals方法がfalseに戻ると、集合中にそのオブジェクトが存在しないと考えて、もう一度ハッシュを行い、そのオブジェクトをハッシュ後に算出された新しいアドレスに置くと、equals方法がtrueに戻ると、集合は、集合の中に既にオブジェクトが存在していると考えられ、そのオブジェクトを集合に追加することはない。
2、equals方法を書き換えるときは、hashCode方法を書き換えなければなりません。javaのセットでは、2つのオブジェクトが等しいかどうかを判断するルールは、
1)二つの対象のhashCodeが等しいかどうかを判断する。
もし等しくないならば、2つの対象も等しくないと思って、終わります。等しい場合は、2に移動します。
2)両オブジェクトがequalsで演算されているかどうかを判断する。
同じでないと、二つのオブジェクトも同じではないと思います。
等しい場合、2つのオブジェクトが等しいかどうかを判断する鍵となる。
hashcode()が等しい場合、equals()の方法も異なることがあります。
public static void main(String args[]){
String s1=new String("zhaoxudong"); // , “zhaoxudong”( ), new 。 .4
String s2=new String("zhaoxudong");
// , 。
System.out.println(s1==s2);//false
System.out.println(s1.equals(s2));//true
System.out.println(s1.hashCode());//s1.hashcode() s2.hashcode() ,
System.out.println(s2.hashCode()); //equals hashCode ,
Set hashset=new HashSet();
hashset.add(s1);
hashset.add(s2); /* s1,s2 , hashset s1 s2 , s2 s1;*/
Iterator it=hashset.iterator();
while(it.hasNext()){
System.out.println(it.next());
} // while ”zhaoxudong”。
これはString類がequals()方法とhashcode()方法を書き換えたからです。しかし、次の手順を見てください。
>public class HashSetTest {
public static void main(String[] args) {
HashSet hs=new HashSet();
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(2,"lisi"));
hs.add(new Student(3,"wangwu"));
hs.add(new Student(1,"zhangsan"));
Iterator it=hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
} } }
class Student {
int num;
String name;
Student(int num,String name) {
this.num=num;
this.name=name; }
public String toString() { return num+":"+name; }
}
出力結果は:
1:zhangsan
1:zhangsan
3:wangwu
2:lisi
なぜhashsetに同じ要素が追加されましたか?これはhashsetの原則と違反していますか?回答:hashcodeによってnewStudent(1,「zhangsan」)オブジェクトを2回作成した場合、生成されたのは異なるハッシュコード値であるため、hashsetは彼を異なる対象として扱ったので、当然この時のequals()方法で返した値も違いません。なぜ、異なるハッシュ・コード値が生成されるのか?なぜかというと、私たち自身が書いたStudent類は、自分のhashcode()とequals()をやり直す方法がないからです。
したがって、比較時には、継承されたobjectクラスのhashcode()方法であり、比較は対象のアドレス(参照アドレス)であり、new法を用いてオブジェクトを作成し、2回生成されたのはもちろん別のオブジェクトです。結果としては、2つのオブジェクトのhashcode()の戻り値が違います。この問題はどう解決しますか?
理由は、Studentクラスで、shcode()とequals()の方法を見直すためです。
class Student{
int num;
String name;
Student(int num,String name){
this.num=num;
this.name=name; }
public int hashCode(){ // hashCode
return num*name.hashCode(); }
public boolean equals(Object o) {
Student s=(Student)o;
return num==s.num && name.equals(s.name); //&& == ,
}
public String toString(){return num+":"+name; }
}
書き換えの方法によれば、new Student(1,「zhangsan」)を2回呼び出したとしても、私たちはオブジェクトのハッシュコードを取得する際に、書き換えの方法によってhashcode()を用いて、取得したハッシュコードは同じに違いない。修正後のプログラムを実行すると、重複要素の問題が解消されていることが分かります。締め括りをつける
この知識は間違いやすいです。理解は深くしなければなりません。多くの実践は原理と定義に対してより深く理解します。何か問題があったらいつでもメッセージを残してください。みなさんの応援に感謝します。