Ketika Anda mengoverride equals() untuk mendefinisikan kesetaraan logis, Anda harus juga mengoverride hashCode() — karena koleksi berbasis hash (, ) bergantung pada kontrak bahwa . Melanggar ini menyebabkan bug yang halus dan sulit ditemukan.
Ketika Anda mengoverride equals() untuk mendefinisikan kesetaraan logis, Anda harus juga mengoverride hashCode() — karena koleksi berbasis hash (, ) bergantung pada kontrak bahwa . Melanggar ini menyebabkan bug yang halus dan sulit ditemukan.
HashMapHashSet// by default, equals() compares IDENTITY (same object?), hashCode() is based on memory address
Person p1 = new Person("Ann", 30);
Person p2 = new Person("Ann", 30);
p1.equals(p2); // false by default — different objects, even with same data
Tanpa mengoverride, dua objek dengan konten identik adalah "tidak sama" — biasanya bukan yang Anda inginkan untuk value objects.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person p = (Person) o;
return age == p.age && Objects.equals(name, p.name); // compare by CONTENT
}
@Override
public int hashCode() {
return Objects.hash(name, age); // MUST be consistent with equals()
}
Kontrak: jika a.equals(b) benar, maka a.hashCode() == b.hashCode() HARUS benar.
Person p1 = new Person("Ann", 30);
Person p2 = new Person("Ann", 30); // equal by our equals()
Set<Person> set = new HashSet<>();
set.add(p1);
set.contains(p2); // ❌ likely FALSE — even though p1.equals(p2)!
Mengapa? HashMap/HashSet pertama-tama menggunakan hashCode() untuk menemukan bucket yang tepat, kemudian equals() di dalamnya. Dengan default (berbasis identitas) hashCode(), p1 dan p2 mendarat di bucket yang berbeda, jadi contains tidak pernah membandingkan mereka — set pikir mereka berbeda. Ini menghasilkan bug yang membingungkan: duplikat dalam Set, pencarian map yang gagal, dll.
1. equal objects → equal hash codes (REQUIRED for correctness)
2. unequal objects MAY have the same hash (collisions are allowed)
3. hashCode() must be consistent (same object → same code, unchanged)
4. equals() must be reflexive, symmetric, transitive, consistent
record Person(String name, int age) {} // records auto-generate equals/hashCode/toString!
Java records (dan IDE generation / Lombok) menghasilkan equals/hashCode yang benar dan konsisten untuk Anda.
Kontrak equals/hashCode adalah salah satu aturan paling penting dan paling sering dilanggar di Java.
Mengoverride equals() tanpa hashCode() merusak koleksi berbasis hash dengan cara yang sulit di-debug: objek yang Anda anggap sama "hilang" di HashMap/HashSet (pencarian gagal, duplikat fantom) karena mereka di-hash ke bucket yang berbeda.
Karena koleksi ini ada di mana-mana, setiap kelas tipe nilai yang digunakan sebagai kunci atau elemen set harus mengoverride keduanya secara konsisten.
Memahami mengapa (mekanisme pencarian bucket-kemudian-equals) — dan menggunakan records atau kode yang dihasilkan untuk membuatnya benar — sangat penting untuk perilaku yang benar dan topik wawancara klasik yang mengungkapkan pemahaman nyata tentang cara kerja koleksi Java.
Perpustakaan pertanyaan wawancara IT dengan jawaban mendetail — dari Junior hingga Senior.
Donasi