2009-11-02 12 views
7

HashSetインスタンスが期待どおりに動作するように見えません。次のように私が使用したコードは次のとおりです。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(); 
    } 
} 

あなたはequals(Object)をオーバーライドする必要がこのコードを出力

[email protected]:~/Documents$ javac testing/Subclass.java 
[email protected]:~/Documents$ javac tester.java 
[email protected]:~/Documents$ java tester 
Set size 2 
Set size 3 
sub acctNbr 007812 
sub acctNbr 007812 
sub acctNbr 007813 
[email protected]:~/Documents$ 
+2

あなたはどのような動作を期待していますか、それはあなたが見ている動作とどのように違うのですか? –

答えて

20

。これを行う代わりにequals(Subclass)equalsメソッドを実装しました。したがって、HashSetは、平等テストのためにObjectに定義されているデフォルトのequals(Object)メソッドを使用しています。

デフォルトのequals(Object)は、オブジェクトIDに基づいて実装されているため、意味的には同じオブジェクトではない2つのオブジェクトを追加することができます。

+4

hashCode()もオーバーライドすることを忘れないでください。 –

+0

OPは既にhashCode()を正しくオーバーライドしていましたが、これはまだ重要なポイントです。 – Adamski

5

Object.equals()を正しく上書きしませんでした。

boolean equals(Subclass other)は、意図したとおりではない第2の方法を作成します。

+0

オプションのオーバーライドタグのみを有効にします。 –

+2

'instanceof'はnull参照に対してfalseを返すので、nullをチェックする必要はありません。 –

+0

@Overrideの厳密なチェックは、問題を直ちに指摘していたはずです。 – andersoj

0

equals(Subclass other)はである必要があります。java.lang.Object.equals()メソッドをオーバーライドする必要があります。おそらくそのセットは基礎となるequals()の実装を呼びます。

+0

ボンベが言ったのはまあまあまあまあです。 – andersoj

0

あなたのequalsメソッドは決して呼び出されません。 equalsのシグネチャは、他のクラス(equalsを実装するクラスを含む)を除いて、Objectを必要とします。

public boolean equals(Object other) { 
    ... 
} 
3

2つのメタ-ポイント:

まず、あなたがメソッドをオーバーライドしていると信じて毎回@Override使用するのが習慣に取得します。そうすれば、サンプルコードがコンパイルに失敗し、問題を発見することができます。

第2に、IDEを使用していて、大胆な警告が強調表示されていないと、設定が間違っています。あなたはそれを修正する必要があります!

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; }を付加価値があるが、それはの定期的な習慣を作るために本当に価値があるではありませんそれ。

1

誰もが正しいpublic boolean equals(Object o)メソッドを無効にする必要があると言ったので、私はほとんど同じ問題を抱えていました。しかしそれだけでは不十分です!

また、public int hashCode()をオーバーライドする必要があります。そうしなかった場合、javaはequalsメソッドを呼び出しません。

関連する問題