質問
私は期待どおりに動作するHashSet
インスタンスを取得するように見えることはできません。次のように私が使用したコードは、次のとおりです。
import testing.Subclass;
import java.util.HashSet;
public class tester {
public static void main(String[] args) throws Exception {
HashSet<Subclass> set = new HashSet<Subclass>();
set.add(new Subclass("007812"));
set.add(new Subclass("007813"));
System.out.println("Set size " + set.size());
set.add(new Subclass("007812"));
System.out.println("Set size " + set.size());
for(Subclass sub : set) {
System.out.println(" sub acctNbr " + sub.getAcctNbr());
}
}
}
サブクラス
public class Subclass implements Comparable<Subclass> {
public Subclass(String acctNbr) {
this.acctNbr = acctNbr;
}
private String acctNbr;
public String getAcctNbr() {
return this.acctNbr;
}
public int compareTo(Subclass other) {
return this.getAcctNbr().compareTo(other.getAcctNbr());
}
public boolean equals(Subclass other) {
if(other.getAcctNbr().equals(this.getAcctNbr()))
return true;
else
return false;
}
public int hashCode() {
return acctNbr.hashCode();
}
}
このコードを出力
sross@sross-workstation:~/Documents$ javac testing/Subclass.java
sross@sross-workstation:~/Documents$ javac tester.java
sross@sross-workstation:~/Documents$ java tester
Set size 2
Set size 3
sub acctNbr 007812
sub acctNbr 007812
sub acctNbr 007813
sross@sross-workstation:~/Documents$
解決
あなたはequals(Object)
をオーバーライドする必要があります。代わりにこれを行うのは、あなたの署名equals
でequals(Subclass)
メソッドを実装しました。その結果、あなたのHashSet
は平等のテストのためにequals(Object)
で定義されたデフォルトのObject
の方法を使用しています。
デフォルトのequals(Object)
の実装は、オブジェクトIDに基づいており、したがって、セットには、意味的に等しい一方で、同じオブジェクトではありません2 String
sを追加する「ことができます」。
他のヒント
あなたは正しくObject.equals()
を上書きしませんでした。
@Override
public boolean equals(Object other) {
if ((other == null) || !(other instanceof Subclass)) {
return false;
}
return ((Sublcass) other).getAcctNbr().equals(this.getAcctNbr());
}
メソッドboolean equals(Subclass other)
は、あなたがする意図したものではない第二の方法を作成します。
2つのメタ・ポイントます:
まず、あなたがメソッドをオーバーライドしていると信じて毎回@Override
使用するのが習慣に取得します。それは、問題を発見するためにあなたをリードし、あなたの例のコードはコンパイルに失敗する原因となっていると思います。
第二に、それは間違って設定されています!あなたはそれを修正する必要があります!
そして、あなたはIDEを使用していない場合 - あなたは本当に、本当にする必要があります。あなたがpublic boolean equals(Subclass other)
を入力するとすぐとして、あなたの可能性の高い問題が何であるかを伝えるテキストの色が変わってしまうと警告が表示される。
ちなみに、私が収束してきたequals()
のための標準的なイディオムはこれです:
@Override public boolean equals(Object object) {
if (object instanceof Subclass) {
Subclass that = (Subclass) object;
return this.anInt == that.anInt
&& this.aString.equals(that.aString); // for example
}
return false;
}
のいくつかのの例では、それはif (object == this) { return true; }
を付加価値があるが、それはそれの定期的な習慣を作るために本当に価値がないのです。
public boolean equals(Object o)
メソッドをオーバーライドする必要が言ったように、私は、ほぼ同じ問題を抱えていました。しかし、それは十分ではありません!
そうでない場合は、Javaは全くpublic int hashCode()
メソッドを呼び出すことはありません(あなたが行ったように)equals
をオーバーライドすることも必要です。
最初の推測は、それはあなたのequals(Subclass other)
のように見えますが、あなたが望むように、equals(Object other)
メソッドをオーバーライドするためにjava.lang.Object.equals()
されるべきです。おそらくセットは、基礎となるequals()
の実装を呼び出してます。
あなたのequalsメソッドが呼び出されることはありません。 equals
の署名は、それが(Object
を実装することを起こるどんなクラスを含む)equals
はなく、他のいくつかのクラスを取ることを要求する。
public boolean equals(Object other) {
...
}