この下の例では、私はまったく同じ内部構造を持つ2つのオブジェクトを作成します。キャリーは何もありませんが、インスタンス変数として値1の両方。私の考えは、私が取る場合のハッシュということですe1
、それはのハッシュと同じでなければなりませんe2
ので、e1.equals(e2)
trueを返す必要があります。
class EqualsChecker {
public static void main(String[] args) {
Elem e1 = new Elem(1);
Elem e2 = new Elem(1);
System.out.println(e1); // EqualsChecker$Elem@6ff3c5b5
System.out.println(e2); // EqualsChecker$Elem@3764951d
System.out.println("e1.equals(e2): " + e1.equals(e2)); // returns false
}
static class Elem {
private int v;
public Elem(int i) {
this.v = i;
}
}
}
次の点を見てくださいhttps://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#hashCode--
- オブジェクトが変更された上で、それは、Javaアプリケーションの実行中に複数回同じオブジェクトで呼び出されるたびに、hashCodeメソッドは一貫して同じ整数を返す必要があり、等号の比較に使用される情報を全く設けられていません。この整数は同じアプリケーションの別の実行へのアプリケーションの1つの実行の一貫性を維持する必要はありません。
- 2つのオブジェクトが等しい(オブジェクト)の方法に従って等しい場合には、同じ整数の結果を生成しなければならない二つの物体の各々にhashCodeメソッドを呼び出します。
- 2つのオブジェクトが等しい(java.lang.Objectの)方法に従って等しくない場合には、別個の整数結果を生成しなければならない二つの物体の各々にhashCodeメソッドを呼び出すことが必要とされません。しかし、プログラマは、等しくないオブジェクトについては異なる整数値が生成するハッシュテーブルの性能を向上させることができることに注意すべきです。
- 合理的に実用的である限り、クラスオブジェクトによって定義されたhashCodeメソッドは、異なるオブジェクトの異なる整数値を返しません。(ハッシュコードは、またはある時点で、オブジェクトのメモリアドレスの一部の機能として実現してもしなくてもよいです。)
さて、次のコードと、その出力を見てみましょう。
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
出力:
true
employee1.hashCode(): 511833308
employee3.hashCode(): 511833308
false
employee2.hashCode(): 1297685781
以来employee3
と同じオブジェクトを指しているemployee1
間、あなたは彼らのために同じハッシュコードを取得している、employee2
別のオブジェクトを指している(それは同じ内容を有しているが、キーワードは、new
メモリ内の別のオブジェクトを作成します)そのため、あなたはまれかもしれません以下のために同じハッシュコードを取得するemployee2
とポイント#4ドキュメントの状態から、上述しました:As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.
あなたはオーバーライドする必要がありますhashCode
2つのオブジェクトが同じ内容などを持つために、同じハッシュコードを返す必要がありますように、方法を
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : code.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
出力:
true
employee1.hashCode(): 128107556
employee3.hashCode(): 128107556
false
employee2.hashCode(): 128107556
実装hashCode
上記のに対して同じハッシュコードを生成employee1
し、employee2
にもかかわらずequals
戻るfalse
(としてのチェックポイント#3ドキュメントから上記)。
オーバーライドの間違った方法は、hashCode
例えば、異なるハッシュコードを返しても、同じオブジェクトを生じ得ます
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : (int) (code.length() * (Math.random() * 100)));
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee1.hashCode() again: " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
出力:
true
employee1.hashCode(): 66066760
employee1.hashCode() again: 66069457
employee3.hashCode(): 66073797
false
employee2.hashCode(): 66074882
これは、オーバーライドの間違った方法でhashCode
起動するためhashCode
のJavaアプリケーションの実行中に複数回、同じオブジェクトには一貫して(ASチェック同じ整数を返さなければならない点#1ドキュメントから上記)。
さて、次のコードと、その出力を見てみましょう。
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEmployee other = (MyEmployee) obj;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
return true;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
出力:
true
employee1.hashCode(): 511833308
employee3.hashCode(): 511833308
true
employee2.hashCode(): 1297685781
のでemployee1.equals(employee2)
戻りtrue
、ハッシュコードも同じ(チェック返さなければならない点#2のドキュメントから上記)。しかしながら、ハッシュコードの値employee1
とemployee2
正確されていない異なります。我々が上書きされていないので、この違いはあるhashCode
方法を。だから、あなたがオーバーライドする時はいつでもequals
、あなたはまた、オーバーライドする必要がありますhashCode
正しい方法をインチ
最後に、下記のを実装するための正しい方法であるhashCode
とequals
:
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : code.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEmployee other = (MyEmployee) obj;
if (age != other.age)
return false;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
出力:
true
employee1.hashCode(): 128107556
employee3.hashCode(): 128107556
true
employee2.hashCode(): 128107556