Apabila anda mengasingkan equals() untuk menentukan kesamaan logik, anda harus juga mengasingkan hashCode() — kerana koleksi berasaskan hash (, ) bergantung pada kontrak yang . Melanggar ini membawa kepada pepijat yang halus dan sukar dicari.
Apabila anda mengasingkan equals() untuk menentukan kesamaan logik, anda harus juga mengasingkan hashCode() — kerana koleksi berasaskan hash (, ) bergantung pada kontrak yang . Melanggar ini membawa kepada pepijat yang halus dan sukar dicari.
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 pengasingan, dua objek dengan kandungan yang sama bukan "sama" — biasanya bukan apa yang anda inginkan untuk objek nilai.
@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) adalah benar, maka a.hashCode() == b.hashCode() MESTI 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 mula-mula menggunakan hashCode() untuk mencari ember yang betul, kemudian equals() di dalamnya. Dengan hashCode() lalai (berasaskan identiti), p1 dan p2 mendarat dalam ember yang berbeza, jadi contains tidak pernah membandingkannya — set itu menganggap mereka berbeza. Ini menghasilkan pepijat yang mengelirukan: pendua dalam Set, pencarian peta yang gagal, dan sebagainya.
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 penjanaan IDE / Lombok) menghasilkan equals/hashCode yang betul dan konsisten untuk anda.
Kontrak equals/hashCode adalah salah satu peraturan Java yang paling penting — dan paling kerap dilanggar.
Mengasingkan equals() tanpa hashCode() memecahkan koleksi berasaskan hash dengan cara yang sukar untuk disahkan: objek yang anda anggap sama "hilang" dalam HashMap/HashSet (pencarian gagal, pendua hantu) kerana mereka hash ke ember yang berbeza.
Memandangkan koleksi ini ada di mana-mana, setiap kelas jenis nilai yang digunakan sebagai kunci atau elemen set mesti mengasingkan kedua-duanya dengan konsisten.
Memahami mengapa (mekanisme pencarian ember-kemudian-sama) — dan menggunakan rekod atau kod yang dihasilkan untuk melakukannya dengan betul — adalah penting untuk kelakuan yang betul dan topik temu duga klasik yang mendedahkan pemahaman sebenar tentang cara kerja koleksi Java.
Pustaka soalan temu duga IT dengan jawapan terperinci — daripada Junior hingga Senior.
Derma