Всем привет, подскажите пожалуйста как правильно переопределить hashCode что б корректно работала такая запись:
LinkedHashSet<Integer> uniqueValues = new LinkedHashSet<Integer>();
Random rnd = new Random();
while(uniqueValues.size() < 5){
number = 1 + rnd.nextInt(5 - 1 + 1);
uniqueValues.add(number);
}
Необходимо что бы коллекции значения не сортировались по возрастанию, а находились в порядке добавления, я так понял для этого необходимо переопределить HashCode(), только чуть не понял где и как
Вам не надо переопределять hashCode
. Элементы будут и так храниться в том порядке добавления. Это свойство LinkedHashSet
.
Методы hashCode()
и equals()
необходимо переопределить для кастомного (Вами созданного) объекта, чтобы определить поведение, при сравнении двух этих объектов. Т.е. надо явно указать, что считать одинаковыми объектами.
Суть Set'a (множества) как раз в том, что в него нельзя добавить объекты, которые уже в нем есть. Т.е. если вы будете добавлять каждый раз один и тот же объект (исходя как раз из equals и hashCode) он не будет добавляться. Использование реализации LinkedHashSet уже подразумевает хранение в порядке добавления.
Допустим у меня есть класс:
class MyClass{
private int id;
private String name;
public MyClass(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
Теперь я создаю Set и помещаю в него два объекта:
Set<MyClass> set = new LinkedHashSet<>();
set.add(new MyClass(1,"1"));
set.add(new MyClass(1,"1"));
set.forEach(myClass -> System.out.println("Element -> id: "+myClass.getId()+"; name: "+myClass.getName()));
Результат:
Element -> id: 1; name: 1
Element -> id: 1; name: 1
Т.е. в текущем множестве находится два объекта. Это происходит потому что все объекты в Java наследуются от класса Object, в котором сравнение объектов происходит по ссылке (на участок в памяти). Т.е. технически это два разных объекта (располагаются в разных участках памяти), и они не равны.
Именно поэтому и необходимо явно переопределить методы equals() и hashCode(), т.к. в них должна описываться логика сравнения двух разных объектов.
Добавляем эти методы в класс MyClass:
@Override
public boolean equals(Object o) {
//Здесь явное сравнение по ссылке
if (this == o) return true;
//Здесь, если объект не является таким же классом то вернет false
if (!(o instanceof MyClass)) return false;
MyClass myClass = (MyClass) o;
//Здесь, если id'шники не равны вернет false
if (getId() != myClass.getId()) return false;
//Здесь, если name не равен null (у того и другого объекта) и они идентичны возвращаем true
return getName() != null ? getName().equals(myClass.getName()) : myClass.getName() == null;
}
@Override
public int hashCode() {
//Здесь складываем значения id и hashCode() строки name и получаем относительно уникальный хэш
int result = getId();
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
return result;
}
Заново запущу код создания Set'a только добавлю еще пару элементов:
Set<MyClass> set = new LinkedHashSet<>();
set.add(new MyClass(1,"1"));
set.add(new MyClass(2,"2"));
set.add(new MyClass(2,"not 2"));//Id совпадают, но name разные
set.add(new MyClass(1,"1"));//Пытаюсь добавить уже существующий элемент
set.add(new MyClass(3,"3"));
set.add(new MyClass(2,"2"));//Пытаюсь добавить уже существующий элемент
set.forEach(myClass -> System.out.println("Element -> id: "+myClass.getId()+"; name: "+myClass.getName()));
Результат:
Element -> id: 1; name: 1
Element -> id: 2; name: 2
Element -> id: 2; name: not 2
Element -> id: 3; name: 3
Как видно из примера идентичные значения не стали добавляться, хотя при этом это разные объекты в памяти. По этой логике я могу отказаться от сравнения поля name, тогда оно будет происходить только по id.
P.S. Для большинства встроенных в Java классов данные методы уже определены, и Вам не нужно это делать явно.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Как сделать background image на столько большим, что бы можно сделать кнопку наверх в виде ракеты который взлетает с космодрома (это наш background image в самом...
Выпадающее меню кнопки попадает по слой другого элемента, который находится нижеХотя у выпадающего меню явно указано абсолютное позиционирование...