Сегодня покажу, как неочевидный баг в
equals()/hashCode() может привести к потере данных при работе с HashMap.Допустим, у вас есть Entity:
public class User {
private String id;
private String name;
// equals/hashCode только по id
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return Objects.equals(id, user.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
Вроде норм. Но теперь добавим такого юзера в
HashMap, а потом... изменим его id:
User user = new User();
user.setId("1");
user.setName("Alice");
Map<User, String> map = new HashMap<>();
map.put(user, "value");
user.setId("2"); // ⚠️ ключ стал "невидимым"
System.out.println(map.get(user)); // null 😱
📌 Почему так происходит?
HashMap ищет ключ по hashCode() → ищет бакет → сравнивает через equals(). А hashCode() уже другой, и объект "теряется".💡 Совет: если вы используете объект как ключ в мапе или добавляете его в Set, не изменяйте его поля, участвующие в
equals()/hashCode()!📌 А как правильно?
- Делайте такие поля
final;- Или используйте неизменяемые типы (
record);- Или не используйте такие объекты как ключи вовсе.
Вот безопасный вариант с
record:
public record User(String id, String name) {}
📲 Мы в MAX
👉@BookJava


