Переопределение хэш-кода и метода equals в java?

У меня есть классы ниже:

public class Sample implements java.io.Serializable{

  //POJO with two fields and getters/setters

   private String name;
   private Integer id;

   //This POJO does not override equals() and hashCode()
}

public class B{
 private Sample sample;

  //here i need override hashcode and equals() based on **sample** property.


}

Когда я попытался переопределить equals() и hashCode() в классе B, я получил следующую ошибку в Eclipse.

Тип поля com.mypackage.Sample не реализует функции hashCode() и equals(). Результирующий код может работать некорректно.

Теперь, как я могу сравнить два экземпляра B, равны они или нет, на основе свойства Sample? Я не могу изменить класс Sample.


person user755806    schedule 10.12.2013    source источник
comment
Возможный дубликат Что пойдет не так, когда суперкласс не переопределяет equals() и hashCode()?. Хотя обратите внимание, что, на мой взгляд, предупреждение ошибочно.   -  person Duncan Jones    schedule 10.12.2013
comment
Эклипс работает няней. Он беспокоится за вас. Игнорируйте его или добавьте методы в Sample.   -  person bmargulies    schedule 10.12.2013
comment
Зная о компараторе и сопоставимом?   -  person dev2d    schedule 10.12.2013


Ответы (2)


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

class Sample implements java.io.Serializable{

    //POJO with two fields and getters/setters

    private String name;
    private Integer id;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    //This POJO does not override equals() and hashCode()
}

public class Beta implements Comparable{
    private Sample sample;

    public Sample getSample() {
        return sample;
    }

    public void setSample(Sample sample) {
        this.sample = sample;
    }

    @Override
    public int compareTo(Object o) {

        if(!(o instanceof Beta)){
            return -1;
        }
        }if(((Beta)o).getSample().getName().equals(this.sample.getName())){
                return 0; // return true if names are equal
            }
            if(((Beta)o).getSample().getId().equals(this.sample.getId())){
            //if name are notequal and IDs are equal, do what you need to do
            }
        return -1;
    }

    public static void main(String[] args) {
        Beta b = new Beta();
        Sample s = new Sample();
        s.setId(10);
        s.setName("Name1");
        b.setSample(s);

        Beta b2 = new Beta();
        Sample s2 = new Sample();
        s2.setId(20);
        s2.setName("Name2");
        b2.setSample(s2);

        System.out.println(b2.compareTo(b));

        Beta b3 = new Beta();
        Sample s3 = new Sample();
        s3.setId(10);
        s3.setName("Name1");
        b3.setSample(s3);

        System.out.println(b3.compareTo(b));
    }
}

Переопределяющий подход

class Sample implements java.io.Serializable{

    //POJO with two fields and getters/setters

    private String name;
    private Integer id;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    //This POJO does not override equals() and hashCode()
}

public class Beta /*implements Comparable*/{
    private Sample sample;

    public Sample getSample() {
        return sample;
    }

    public void setSample(Sample sample) {
        this.sample = sample;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Beta other = (Beta) obj;

        if ((this.getSample() == null) && (other.getSample() == null)){
            return true;
        }
        if ((this.getSample().getId().equals(other.getSample().getId())) && (this.getSample().getName().equals(other.getSample().getName()))) {
            return true;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 53 * hash + (this.getSample().getName() != null ? this.getSample().getName().hashCode() : 0);
        hash = 53 * hash + (this.getSample().getId() != null ? this.getSample().getId().hashCode() : 0);
        return hash;
    }


/*  @Override
    public int compareTo(Object o) {

        if(!(o instanceof Beta)){
            return -1;
        }
        if(((Beta)o).getSample().getId().equals(this.sample.getId()) && ((Beta)o).getSample().getName().equals(this.sample.getName())){
            return 0;
        }
        return -1;
    }*/

    public static void main(String[] args) {
        Beta b = new Beta();
        Sample s = new Sample();
        s.setId(10);
        s.setName("Name1");
        b.setSample(s);

        Beta b2 = new Beta();
        Sample s2 = new Sample();
        s2.setId(20);
        s2.setName("Name2");
        b2.setSample(s2);

        System.out.println(b2.equals(b));

        Beta b3 = new Beta();
        Sample s3 = new Sample();
        s3.setId(10);
        s3.setName("Name1");
        b3.setSample(s3);

        System.out.println(b3.equals(b));
    }
person dev2d    schedule 10.12.2013
comment
VD, да, это именно то, что я искал. Мое требование - сначала мне нужно проверить свойство equals против свойства имени Sample. ЕСЛИ имена равны, то оба объекта равны. Если имена не равны, мне нужно проверить на равенство свойство ID образца. Как я могу это сделать? Спасибо! - person user755806; 10.12.2013
comment
я отредактировал код в соответствии с вашим требованием, вы можете обратиться к переопределяющему подходу из stackoverflow.com/questions/8180430/ - person dev2d; 10.12.2013
comment
я также отредактировал код для переопределения методов hashcode и equals - person dev2d; 10.12.2013

Если вы явно не переопределите .equals(), они будут сравниваться исключительно на основе их ссылок (несмотря на отсутствие equals(), каждый объект наследует один из Object). Если вы хотите, чтобы B сравнивалось только с Sample, просто сделайте следующее:

@Override
public boolean equals(Object o)
{
     if (o istanceof B)
     {
         return sample.equals(o.sample)
     }

     return false;
}

Кроме того, вы должны переопределить hashCode()compareTo()), чтобы сохранить договор между equals() и hashCode(). Следовательно, у вас также должно быть следующее:

@Override
public int hashCode()
{
    return sample.hashCode();
}

EDIT (в ответ на комментарий):

Мое требование: сначала мне нужно проверить свойство equals на свойство "name" Sample. ЕСЛИ имена равны, то оба объекта равны. Если имена не равны, мне нужно проверить равенство со свойством «ID» образца. Как я могу это сделать? Спасибо!

Определение эквивалентности Samples должно выполняться в Sample путем переопределения equals(). Если equals() вместо Sample основано на name и id, то все в порядке. Если вы хотите сравнить Samples в B не так, как обычно, то вы не сможете сохранить контракт между equals() и hashCode() для B, если вы используете hashCode() или equals() из Sample, что означает, что ваши hashCode() и equals() для B должно быть невозможно позвонить equals() или hashCode() из Sample. См. этот учебник, чтобы узнать, как для переопределения на основе определенных полей.

person Steve P.    schedule 10.12.2013
comment
Я старался. Но все же я получаю. Тип поля com.mypackage.Sample не реализует hashCode() и equals() - результирующий код может работать неправильно. какие-либо предложения? - person user755806; 10.12.2013
comment
@user755806 user755806 Это определенно работает, я считаю, что ваша IDE просто сообщает вам, что вы явно не переопределяете hashCode() и equals(). Убедитесь, что вы также переопределили hashCode() для B — я внес правку, в которой указано, как это сделать. Если этого не сделать, вы не будете поддерживать контракт equals() и hashCode(). Если ваша IDE все еще кричит на вас, это просто предупреждение, чтобы убедиться, что вы понимаете, что для Sample вы используете методы по умолчанию вместо переопределения. - person Steve P.; 10.12.2013
comment
Стив, спасибо за ответ. Мое требование: сначала мне нужно проверить свойство equals на свойство имени образца. ЕСЛИ имена равны, то оба объекта равны. Если имена не равны, мне нужно проверить на равенство свойство ID образца. Как я могу это сделать? Спасибо! - person user755806; 10.12.2013
comment
@user755806 user755806 Вы задаете здесь несколько вопросов... Это должно быть обработано в Sample. Как и при переопределении equals() из Sample. Если это не тот способ, которым обычно следует сравнивать Samples, или вы не можете этого сделать, то вы не сможете сохранить контракт equals() и hashCode(), что означает, что вы не можете делай что хочешь. См. этот руководство. как переопределить на основе определенных полей. - person Steve P.; 10.12.2013