Anotasi @EqualsAndHashCode
yang menggunakan atribut Long seperti pk
dapat menyebabkan beberapa perilaku yang tidak terduga saat digunakan dengan struktur berbasis hash (seperti HashSet).
misalnya.:
<strong i="9">@Entity</strong>
@EqualsAndHashCode(of = "pk")
class Foo {
<strong i="10">@Id</strong>
private Long pk;
private LocalDate createdAt;
}
<strong i="13">@Entity</strong>
class Foo {
<strong i="14">@Id</strong>
private Long pk;
private LocalDate createdAt;
public int hashCode() {
int PRIME = true;
int result = 1;
Object $pk = this.getPk();
int result = result * 59 + ($pk == null ? 43 : $pk.hashCode());
return result;
}
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
}
Jadi ketika instance dengan pk = null dan lainnya dengan pk = 43, itu akan mengembalikan kode hash yang sama dan itu dapat dianggap sama pada struktur berbasis hash, yang sebenarnya tidak.
Dan dalam kasus untuk menggunakan OmniFaces ListConverter yang menggunakan toString
kami memiliki masalah yang sama.
Mungkin mengembalikan kode hash dari instance objek daripada konstanta hardcoded
Apakah Anda sudah mengambil skenario ini, atau apakah Anda tahu cara untuk mengatasi situasi ini?!
Informasi versi
Jadi ketika instance dengan pk = null dan lainnya dengan pk = 43, itu akan mengembalikan kode hash yang sama
Ini tidak masalah. Selain itu, akan selalu ada tabrakan hash, apa pun yang Anda pilih.
Perhatikan bahwa Arrays.hashCode
, String.hashCode
dan banyak lainnya menghasilkan banyak tabrakan, yang sebenarnya tidak perlu.
Mungkin mengembalikan kode hash dari instance objek daripada konstanta hardcoded
Dalam kode saya yang ditulis secara manual, saya menegaskan bahwa itu tidak dipanggil sebelum id
ditetapkan. Itu pasti aneh, tapi begitu juga semua alternatif.
Dimungkinkan untuk membuat parameter anotasi yang dapat memberi tahu nilai mana yang harus digunakan ketika PK adalah nol, dalam kasus ini. Untuk standar 43.
Ini akan memberi lebih banyak kontrol kepada pengembang.
@EqualsAndHashCode(of = "pk", ifAnyNull = -1)
Jadi itu akan menggunakan -1 sebagai gantinya 43, untuk bidang apa pun yang nol
43 mungkin sama bagusnya dengan nomor lainnya, dan lebih baik dari -1, 0 dan 1. Membuatnya dapat dikonfigurasi menambah beban pemeliharaan untuk nilai tambah yang sangat rendah.
Menggunakan kode hash Identity untuk null akan melanggar kontrak yang sama.
Komentar yang paling membantu
43 mungkin sama bagusnya dengan nomor lainnya, dan lebih baik dari -1, 0 dan 1. Membuatnya dapat dikonfigurasi menambah beban pemeliharaan untuk nilai tambah yang sangat rendah.
Menggunakan kode hash Identity untuk null akan melanggar kontrak yang sama.