Почему HashSet может хранить «одинаковые» объекты? Представим класс пользователя: public class User {

private final Long id; private final String name;

public User(Long id, String name) { this.id = id; this.name = name; } } Создадим два объекта: User user1 = new User(1L, "Ivan"); User user2 = new User(1L, "Ivan");

Set users = new HashSet<>();

users.add(user1); users.add(user2);

System.out.println(users.size()); Интуитивно хочется получить: 1 Ведь пользователи выглядят одинаково. Но результат будет: 2 Почему? Для Java это два разных объекта Мы создали их отдельно: new User(...) new User(...) А методы: equals() hashCode() в User не переопределили. Поэтому используется реализация из Object. Упрощённо Java воспринимает их так: user1 != user2 даже если поля внутри одинаковые. Причём здесь HashSet? HashSet использует: hashCode() чтобы понять, где искать объект, а затем: equals() чтобы проверить, действительно ли объекты равны. Поэтому для объектов, которые должны считаться одинаковыми по значению, обычно нужно корректно определить оба метода. Например: import java.util.Objects;

public class User {

private final Long id; private final String name;

public User(Long id, String name) { this.id = id; this.name = name; }

@Override public boolean equals(Object o) { if (this == o) { return true; }

if (!(o instanceof User user)) { return false; }

return Objects.equals(id, user.id); }

@Override public int hashCode() { return Objects.hash(id); } } Теперь два пользователя с одинаковым id считаются одинаковыми: users.add(new User(1L, "Ivan")); users.add(new User(1L, "Ivan"));

System.out.println(users.size()); Результат: 1 Почему нельзя переопределить только equals()? Потому что контракт Java требует: Если два объекта равны через equals() , их hashCode() тоже должен быть одинаковым. Иначе HashSet или HashMap могут искать объект совсем не там, куда он был помещён. Получаются очень неприятные баги: объект вроде есть ↓ contains() говорит false или: логически одинаковые объекты ↓ лежат как разные элементы Короткий вопрос Что выведет этот код после корректной реализации equals() и hashCode() по id? Set users = new HashSet<>();

users.add(new User(1L, "Ivan")); users.add(new User(1L, "Petr"));

System.out.println(users.size()); Если равенство определяется только по id, подумайте: имена разные, но считаются ли объекты разными для HashSet? #java #backend #как_это_работает