Когда java.util.Set проверяет наличие дубликатов

У меня очень простой вопрос: когда java.util.Set проверяет, являются ли добавляемые объекты дубликатами?

Потому что у меня есть класс модели, как показано ниже, который переопределяет как методы equals, так и методы hashcode.

public class SampleModel implements Comparable {
    private String name;

    public SampleModel(String name) {
        this.name = name;
    }

    // Setter and Getter omitted
    @Override
    public boolean equals(Object arg0) {
        boolean eq = false;

        if (arg0 instanceof SampleModel
                && this.name.equalsIgnoreCase(((SampleModel) arg0).name)) {
            eq = true;
        }
        return eq;
    }

    @Override
    public int compareTo(Object arg0) {
        return this.name.compareTo(((SampleModel) arg0).name);
    }

    @Override
    public int hashCode() {
        return this.name.length();
    }
}

Вот как я использую объекты модели в HashSet.

    SampleModel s1 = new SampleModel("Satya");
    SampleModel s2 = new SampleModel("Katti");

    Set<SampleModel> samSet = new HashSet<SampleModel>();
    System.out.println(samSet.add(s1));
    System.out.println(samSet.add(s2));

    s2.setName("Satya");
    System.out.println(s2.getName());
    System.out.println(s1 + ", " + s2);

В соответствии с предложением о равенстве объекты одинаковы и равны, но HashSet будет содержать дубликаты.

Происходит ли какое-либо нарушение в отношении равенства или хэш-кода? Если этот код в порядке, то есть ли способы предотвратить добавление дубликатов?

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


person Satya    schedule 30.05.2012    source источник


Ответы (2)


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

Это верно.

Точнее, код в вашем вопросе нарушает следующую часть Set контракт:

Примечание. Следует проявлять большую осторожность, если изменяемые объекты используются в качестве элементов набора. Поведение набора не указано, если значение объекта изменяется таким образом, что это влияет на сравнение равенства, в то время как объект является элементом набора. Частный случай этого запрета состоит в том, что множество не может содержать себя как элемент.

Как только вы нарушаете договор, все ставки снимаются.

person NPE    schedule 30.05.2012
comment
При этом проверка дубликатов происходит во время вызова add, как указано в Javadoc. add(e) возвращает true, если e еще не было в наборе и с тех пор было добавлено, и false, если он уже был в наборе. - person Louis Wasserman; 30.05.2012

Пример для понимания:

import java.util.*;

public class Vector1{

  public static void main(String args[]){


    Set v=new HashSet();
    Student st=new Student("12","naushad");
    Student st1=new Student("12","naushad");
    v.add(st1);
    v.add(st);
    System.out.println(st.hashCode());
    st.sname="shouzia";
    System.out.println(st.hashCode());

    v.add(st);
    v.add(st);
    v.add("naushad");
    v.add("naushad");
    v.add("naushad");

    System.out.println(v);
    }

}

class Student{

    public String sid;
    public String sname;

    Student(String sid,String sname){
        this.sid=sid;
        this.sname=sname;
    }

    public String toString(){

        return sid+"\t"+sname;
    }

}

У меня есть экземпляр двух объектов с одинаковыми данными, и они будут храниться в наборе, потому что оба содержат разные хэш-коды, поэтому здесь нет необходимости сравнивать метод equals().

если метод hashcode() возвращает тот же хэш-код, то он проверит метод equals() со свойством объекта и проверит, есть ли изменения в свойстве объекта или нет?. В зависимости от результата он сохранит этот объект в наборе или нет.

person Naushad Pinjari    schedule 08.09.2014