HashSet.contains не работает должным образом с hashCode и равно - PullRequest
0 голосов
/ 20 октября 2011

У меня есть класс MyClass:

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;
    }



}

Ответы [ 2 ]

2 голосов
/ 20 октября 2011

Ваш метод equals () вообще не читается.Поскольку вы используете HashCodeBuilder в hashCode (), почему бы не использовать 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();
}
1 голос
/ 20 октября 2011

Каждый класс должен иметь дело только со своими переменными при вычислении equals и хэш-кода.Итак, в вашем MyClass вместо вызова getWeight() вы должны использовать хеш-код суперкласса.Как и вы с equals() !.В этом случае эффект будет таким же.

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

    return res;
}

Это означает, что любые изменения в базовом классе, которые могут повлиять на равенства и хэш-код, ограничены классом, и вам не нужно обновлять подклассы.

(На самом деле это не ответ, скорее наблюдение, но оно слишком велико для комментария)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...