2011-10-20 4 views
0

I持っていると呼ばれるクラスのMyClass:HashSet.containsが動作しません

public class MyClass extends abstractClass implements 
     someInterface { 

    Set<VNode> relation_; 
    Set<VNode> x_; 
    Set<VNode> y_; 


    @Override 
    public boolean equals(Object obj) { 

     if (!super.equals(obj)) { 
      return false; 
     } 

     if (this == obj) { 
      return true; 
     } 
     if (obj == null) { 
      return false; 
     } 
     if (!(obj instanceof MyClass)) { 
      return false; 
     } 
     MyClass other = (MyClass) obj; 

     if (relation_ == null) { 
      if (other.relation_ != null) { 
       return false; 
      } 
     } else if (!relation_.equals(other.relation_)) { 
      return false; 
     } 
     if (x_ == null) { 
      if (other.x_ != null) { 
       return false; 
      } 
     } else if (!x_.equals(other.x_)) { 
      return false; 
     } 
     if (y_ == null) { 
      if (other.y_ != null) { 
       return false; 
      } 
     } else if (!y_.equals(other.y_)) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public int hashCode() { 
     int res = new HashCodeBuilder(17, 37).append(relation_).append(x_) 
       .append(y_).append(getWeight()).toHashCode(); 

     return res; 
    } 
} 

抽象クラスは次のとおりです。

public abstract class abstractClass { 

    double weight_; 


    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj == null) { 
      return false; 
     } 
     if (!(obj instanceof abstractClass)) { 
      return false; 
     } 
     abstractClass other = (abstractClass) obj; 
     if (Double.doubleToLongBits(weight_) != Double 
       .doubleToLongBits(other.weight_)) { 
      return false; 
     } 
     return true; 
    } 

    public double getWeight() { 
     return weight_; 
    } 


    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     long temp; 
     temp = Double.doubleToLongBits(weight_); 
     result = prime * result + (int) (temp^(temp >>> 32)); 
     return result; 
    } 

} 

を今、私はHashSet<MyClass> s1を持っている場合と、 MyClass i1であっても、s1は、s1i,s1i.equals(i1)=true,s1i.hashCode()=i1.hashCode(),s1.contains(i1)の場合にはfalseとなる。

説明はありますか?

他のクラス:

public class VNode { 

    Mention mention_; 


    @Override 
    public boolean equals(final Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj == null) { 
      return false; 
     } 
     if (!(obj instanceof VNode)) { 
      return false; 
     } 
     VNode other = (VNode) obj; 
     if (mention_ == null) { 
      if (other.mention_ != null) { 
       return false; 
      } 
     } else if (!mention_.equals(other.mention_)) { 
      return false; 
     } 
     return true; 
    } 


    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result 
       + ((mention_ == null) ? 0 : mention_.hashCode()); 
     return result; 
    } 



} 




public class Mention extends Range { 


    private final int       id_; 


    public Mention(final int start, final int end) { 
     super(start, end); 

     id_ = getNextMentionID(); 
    } 

} 





public class Range { 


    private final int start_; 

    private final int end_; 

    /** 
    * Contr. 
    * 
    * @param start 
    * @param end 
    */ 
    public Range(final int start, final int end) { 
     start_ = start; 
     end_ = end; 
    } 



    @Override 
    public boolean equals(final Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj == null) { 
      return false; 
     } 
     if (!(obj instanceof Range)) { 
      return false; 
     } 
     Range other = (Range) obj; 
     if (end_ != other.end_) { 
      return false; 
     } 
     if (start_ != other.start_) { 
      return false; 
     } 
     return true; 
    } 



    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + end_; 
     result = prime * result + start_; 
     return result; 
    } 



} 
+1

VNODEクラスの 'のhashCode()'メソッドを投稿してください。 – Stephan

+0

範囲が等しい場合、2つの言及は等しいですか? IDは関係ありませんか? – Stephan

+0

はい、IDは等しいとみなされません。 – myahya

答えて

1

のequalsとhashCodeを計算する際に各クラスにのみ独自の変数を考慮しなければなりません。したがって、getWeight()を呼び出す代わりにMyClassでは、スーパークラスのハッシュコードを使用する必要があります。あなたはequals()と同じように!この場合、効果は同じになります。

public int hashCode() { 
    int res = new HashCodeBuilder(super.hashcode(), 37).append(relation_).append(x_) 
      .append(y_); 

    return res; 
} 

これはイコールとハッシュコードに影響を与える可能性がある基底クラスへの変更は、クラスに限定され、あなたがサブクラスを更新する必要がないことを意味します。

(そうでもない答えは、より多くの観察が、コメントのためにその大きすぎる)

+0

apache commons-langが使用されている場合、ObjectUtils.hashCodeMulti(Object ..)は高速で、各hashCode()呼び出しで新しいオブジェクトを作成しません。 – Stephan

2

あなたのequals()メソッドがまったく読めません。 hashCode()でHashCodeBuilderを使用しているので、なぜEqualsBuilderも使用しないのはなぜですか?

バージョンA)

public boolean equals(Object obj){ 
    if(obj == null || obj.getClass()!=getClass()){ 
     return false; 
    } 
    MyClass other = (MyClass) obj; 
    return new EqualsBuilder() 
     // check parent properties first 
     .append(this.getWeight(), other.getWeight()) 
     .append(this.relation_, other.relation_) 
     .append(this.x_, other.x_) 
     .append(this.y_, other.y_) 
     .isEquals(); 
} 

バージョンB)

public boolean equals(Object obj){ 
    // delegate to parent equals first 
    if(!super.equals(obj)){ 
     return false; 
    } 
    MyClass other = (MyClass) obj; 
    return new EqualsBuilder() 
     .append(this.relation_, other.relation_) 
     .append(this.x_, other.x_) 
     .append(this.y_, other.y_) 
     .isEquals(); 
} 
+0

あなたはスーパーコールを忘れています。 'getClass()'コールでも問題が発生します。少なくとも、場合によっては不必要な制限が導入されます。 – Voo

+0

@Voo no、 'instanceof'の代わりに' getClass() 'を使うのは機能であり、バグではありません。それは私がサブタイプではなく同じタイプを扱っていることを保証します。それ以外の場合は、非対称equals()があります。 –

+0

しかし、equalsチェックにgetWeight()を追加して、親クラスの関連プロパティもチェックしました。実際には2つの異なるバージョンでそれを行うために2番目のバージョンを追加しました –

関連する問題