Когда выполняется 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 будет содержать дубликаты.

Существует ли какое-либо нарушение w.r.t равно или hashcode? Если этот код в порядке, то какие-либо способы предотвратить дублирование?

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

Ответ 1

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

Это правильно.

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

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

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

Ответ 2

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

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

}

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

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