Saya ingin tahu, apa pendapat orang-orang di sini tentang menggunakan
org.apache.commons.lang.builder
EqualsBuilder
/ HashCodeBuilder
untuk mengimplementasikan equals
/ hashCode
? Apakah ini akan menjadi praktik yang lebih baik daripada menulis sendiri? Apakah ini berfungsi baik dengan Hibernate? Apa pendapatmu?
155
reflectionEquals
danreflectionHashcode
fungsi; kinerja adalah pembunuh mutlak.Jawaban:
Pembangun commons / lang sangat bagus dan saya telah menggunakan mereka selama bertahun-tahun tanpa overhead kinerja yang nyata (dengan dan tanpa hibernasi). Tetapi seperti yang ditulis Alain, cara Jambu bahkan lebih baik:
Inilah contoh Kacang:
Inilah equals () dan hashCode () diimplementasikan dengan Commons / Lang:
dan di sini dengan Java 7 atau lebih tinggi (terinspirasi oleh Guava):
Catatan: kode ini awalnya merujuk Guava, tetapi seperti yang ditunjukkan oleh komentar, fungsi ini telah diperkenalkan di JDK, jadi Guava tidak lagi diperlukan.
Seperti yang Anda lihat, versi Guava / JDK lebih pendek dan menghindari objek pembantu yang berlebihan. Dalam kasus yang sama, itu bahkan memungkinkan untuk hubungan pendek evaluasi jika
Object.equals()
panggilan sebelumnya mengembalikan false (agar adil: commons / lang memilikiObjectUtils.equals(obj1, obj2)
metode dengan semantik identik yang dapat digunakan alih-alihEqualsBuilder
memungkinkan hubungan pendek seperti di atas).Jadi: ya, pembangun lang commons lebih disukai daripada yang dibangun secara manual
equals()
danhashCode()
metode (atau monster mengerikan yang Eclipse akan hasilkan untuk Anda), tetapi versi Java 7+ / Guava bahkan lebih baik.Dan catatan tentang Hibernate:
hati-hati menggunakan koleksi malas dalam implementasi equals (), hashCode (), dan toString () Anda. Itu akan gagal total jika Anda tidak memiliki Sesi terbuka.
Catatan (kira-kira sama dengan ()):
a) di kedua versi sama dengan () di atas, Anda mungkin ingin menggunakan salah satu atau kedua pintasan ini juga:
b) tergantung pada interpretasi Anda terhadap kontrak equals (), Anda juga dapat mengubah baris
untuk
Jika Anda menggunakan versi kedua, Anda mungkin juga ingin memanggil
super(equals())
di dalamequals()
metode Anda . Pendapat berbeda di sini, topiknya dibahas dalam pertanyaan ini:(Meskipun ini tentang
hashCode()
, hal yang sama berlaku untukequals()
)Catatan (terinspirasi oleh Komentar dari kayahr )
Objects.hashCode(..)
(seperti yang mendasarinyaArrays.hashCode(...)
) mungkin berkinerja buruk jika Anda memiliki banyak bidang primitif. Dalam kasus seperti itu,EqualsBuilder
mungkin sebenarnya merupakan solusi yang lebih baik.sumber
equals
. Guava mengubah semua nilai menjadi objek, commons-lang hanya membuat satu objek baru.Teman-teman, bangun! Karena Java 7 ada metode pembantu untuk equals dan kode hash di perpustakaan standar. Penggunaannya sepenuhnya setara dengan penggunaan metode Guava.
sumber
Jika Anda tidak ingin bergantung pada pustaka pihak ke-3 (mungkin Anda menjalankan perangkat dengan sumber daya terbatas) dan Anda bahkan tidak ingin mengetikkan metode Anda sendiri, Anda juga dapat membiarkan IDE melakukan pekerjaan, misalnya dalam penggunaan gerhana
Anda akan mendapatkan kode 'asli' yang dapat Anda konfigurasi sesuai keinginan dan yang harus Anda dukung saat perubahan.
Contoh (eclipse Juno):
sumber
equals
. Jika Anda tidak ingin bergantung pada pustaka pihak ke-3, maka tulis metode satu baris sepertiObjects.equal
Anda. Bahkan ketika digunakan hanya sekali atau dua kali, itu membuat kodenya jauh lebih baik!equals
/hashCode
metode satu baris ???EqualsBuilder dan HashCodeBuilder memiliki dua aspek utama yang berbeda dari kode yang ditulis secara manual:
EqualsBuilder dan HashCodeBuilder memudahkan untuk membandingkan bidang yang bisa menjadi nol. Dengan kode yang ditulis secara manual, ini menghasilkan banyak boilerplate.
Sebaliknya, EqualsBuilder akan membuat instance per metode panggilan yang sama. Jika metode equals Anda sering dipanggil, ini akan membuat banyak contoh.
Untuk Hibernate, implementasi hashCode sama dan tidak ada bedanya. Mereka hanyalah detail implementasi. Untuk hampir semua objek domain yang dimuat dengan hibernate overhead runtime (bahkan tanpa analisis escape) dari Builder dapat diabaikan . Database dan overhead komunikasi akan signifikan.
Seperti yang disebutkan skaffman, versi refleksi tidak dapat digunakan dalam kode produksi. Refleksi akan menjadi lambat dan "implementasi" tidak akan benar untuk semua kecuali kelas yang paling sederhana. Memperhatikan semua anggota juga berbahaya karena anggota yang baru diperkenalkan mengubah perilaku metode yang sama. Versi refleksi dapat bermanfaat dalam kode uji.
sumber
Jika Anda tidak menulis sendiri, ada juga kemungkinan untuk menggunakan jambu google (sebelumnya google collections)
sumber
Jika Anda hanya berurusan dengan kacang entitas di mana id adalah kunci utama, Anda dapat menyederhanakan.
sumber
Menurut pendapat saya itu tidak cocok dengan Hibernate, terutama contoh dari jawaban yang membandingkan panjang, nama dan anak-anak untuk beberapa entitas. Hibernate menyarankan untuk menggunakan kunci bisnis untuk digunakan dalam equals () dan hashCode (), dan mereka memiliki alasannya. Jika Anda menggunakan generator equals otomatis () dan kode hash () pada kunci bisnis Anda, tidak apa-apa, hanya masalah kinerja yang perlu dipertimbangkan seperti yang disebutkan sebelumnya. Tetapi orang biasanya menggunakan semua properti apa yang IMO sangat salah. Misalnya saya sedang mengerjakan proyek di mana entitas ditulis menggunakan Pojomatic dengan @AutoProperty, apa yang saya anggap sebagai pola yang sangat buruk.
Dua skenario utama mereka untuk menggunakan kode hash () dan equals () adalah:
Jadi mari kita asumsikan entitas kita terlihat seperti ini:
Keduanya adalah entitas yang sama untuk Hibernate, yang diambil dari beberapa sesi di beberapa titik (id dan kelas / tabelnya sama). Tetapi ketika kita menerapkan auto equals () kode hash () pada semua alat peraga, apa yang kita miliki?
Jadi, untuk 99% proyek yang saya buat, kami menggunakan implementasi equals () dan hashCode () yang dituliskan sekali dalam kelas entitas dasar, yang konsisten dengan konsep Hibernate:
Untuk entitas sementara saya melakukan hal yang sama seperti yang akan dilakukan Hibernate pada langkah kegigihan, yaitu. Saya menggunakan pertandingan contoh. Untuk objek persisten saya membandingkan kunci unik, yaitu tabel / id (saya tidak pernah menggunakan kunci komposit).
sumber
Untuk berjaga-jaga, orang lain akan merasa berguna, saya telah datang dengan kelas Helper ini untuk perhitungan kode hash yang menghindari overhead penciptaan objek tambahan yang disebutkan di atas (pada kenyataannya, overhead metode Objects.hash () bahkan lebih besar ketika Anda memiliki pewarisan karena akan membuat array baru di setiap level!).
Contoh penggunaan:
Pembantu HashCode:
Saya telah memperkirakan bahwa 10 adalah jumlah maksimum properti yang masuk akal dalam model domain, jika Anda memiliki lebih banyak, Anda harus memikirkan refactoring dan memperkenalkan lebih banyak kelas daripada mempertahankan tumpukan String dan primitif.
Kekurangannya adalah: tidak berguna jika Anda memiliki primitif dan / atau array yang perlu Anda hash secara mendalam. (Biasanya ini adalah kasus ketika Anda harus berurusan dengan benda datar (transfer) yang berada di luar kendali Anda).
sumber