Apache Commons EqualsBuilder dan HashCodeBuilder

Saya sebelumnya membuat blog di Apache Commons ToStringBuilder dan membahas bagaimana hal itu menghilangkan banyak kebosanan yang biasanya terkait dengan penerapan metode toString. Sementara mengimplementasikan toString () memberikan nilai yang signifikan dalam debugging dan logging dan merupakan praktik yang direkomendasikan dalam Java Efektif Joshua Bloch (Item 10 dalam Edisi Kedua), biasanya tidak mempengaruhi logika dan kinerja aplikasi (kecuali toString () secara khusus digunakan sebagai bagian dari logika). Namun, ada metode yang ditentukan dalam Objek yang memengaruhi logika dan kinerja dalam aplikasi dan dua di antaranya [sama dengan () dan kode hash ()] dibahas dalam entri blog ini.

Meskipun hashCode () dan equals () biasanya memengaruhi logika dan kinerja lebih dari yang dilakukan toString (), keduanya juga seringkali lebih rumit untuk diterapkan dengan benar. Banyak pengembang Java mengikuti saran Joshua Bloch untuk menerapkan metode ini seperti yang dijelaskan di Java Efektif (di mana 18 halaman dari 315 halaman inti dikhususkan untuk kedua metode ini). Misalnya, artikel Hashtables: Saat Anda Membuat Objek Kunci Sendiri di Hashtable, Hati-hati merangkum aturan yang harus dipatuhi oleh metode equals () dan memberikan rekomendasi Bloch dalam kode Java. Artikel Hashing it Out: Designing hashCode () and equals () Effectively and Correctly juga membahas bagaimana mengimplementasikan dua metode penting ini (sama dengan dan hashCode). Tentu saja, aturan termudah untuk diingat adalah ketika salah satu dari dua metode ini diganti, yang lainnya juga harus diganti.

Karena bisa jadi sulit untuk mengimplementasikan hashCode () dan equals () dengan benar, akan sangat membantu jika implementasi yang dapat digunakan kembali ini disediakan sebagai bagian dari paket builder Apache Commons Lang (paket yang sama yang berisi ToStringBuilder yang disebutkan sebelumnya). Lebih baik lagi, implementasi ini secara eksplisit ditulis untuk mengikuti saran Bloch yang sering dikutip seperti yang dijelaskan dalam dokumentasi Javadoc untuk EqualsBuilder dan HashCodeBuilder.

Dalam entri blog saya di ToStringBuilder, saya mendemonstrasikan dan banyak menggunakan kemampuan reflektifnya. Saya kurang cenderung menggunakan kemampuan refleksi dalam hubungannya dengan EqualsBuilder dan HashCodeBuilder karena metode ini sering digunakan dalam situasi di mana kinerja menjadi masalah utama. Detail tentang penerapan penggunaan EqualsBuilder dan HashCodeBuilder berbasis refleksi tersedia di sini dan di deskripsi Javadoc masing-masing untuk kelas-kelas ini.

Contoh kode yang digunakan dalam entri blog ini sangat sederhana dan hanya menggores permukaan dari apa yang mampu dicapai oleh EqualsBuilder dan HashCodeBuilder. Namun, kode contoh memberikan contoh sederhana penggunaan umum kedua kelas ini. Bonus tambahannya adalah kode tersebut juga mendemonstrasikan Commons CLI dan Commons Lang ToStringBuilder beraksi juga.

Kelas pertama yang harus dilihat adalah kelas SimpleDataExample karena itu adalah kelas yang sebenarnya berisi implementasi metode equals () dan hashCode () menggunakan EqualsBuilder dan HashCodeBuilder masing-masing. Contoh ini juga menggunakan ToStringBuilder untuk mengimplementasikan metode toString () .

package dustin.builders; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; /** * This is a "simple" data class intended for demonstration of Apache Commons * EqualsBuilder and HashCodeBuilder. This is an immutable class and all of its * state must be provided at construction. * * @author Dustin */ public class SimpleDataExample { /** ID associated with this class. */ private final Long id; /** Name of data (does not need to be unique). */ private final String name; /** * Constructor accepting arguments to populate my state. * * @param newId ID of this object instance. * @param newName Name of this object instance. */ public SimpleDataExample( final Long newId, final String newName) { this.id = newId; this.name = newName; } /** Private constructor - not meant to be used. */ private SimpleDataExample() { this.id = null; this.name = null; } /** * Provide my ID. * * @return My ID. */ public Long getId() { return this.id; } /** * Provide my name. * * @return My name. */ public String getName() { return this.name; } /** * My hash code implementation. * * @return My hash code. */ @Override public int hashCode() { return new HashCodeBuilder() .append(this.id) .append(this.name) .toHashCode(); } /** * My implementation of equals() method. The NetBeans-generated version is * left in place (but commented out) to notice the order of magnitude of code * required without EqualsBuilder. * * @param obj The object to compare to me for equality. * @return true if the other object and I are equal; false otherwise. */ @Override public boolean equals(Object obj) { if (obj instanceof SimpleDataExample == false) { return false; } if (this == obj) { return true; } final SimpleDataExample otherObject = (SimpleDataExample) obj; return new EqualsBuilder() .append(this.id, otherObject.id) .append(this.name, otherObject.name) .isEquals(); /* if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final SimpleDataExample other = (SimpleDataExample) obj; if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) { return false; } if (this.name != other.name && (this.name == null || !this.name.equals(other.name))) { return false; } return true; */ } /** * Provide String representation of me. * * @return String representation of me. */ @Override public String toString() { return new ToStringBuilder(this) .append("ID", this.id) .append("Name", this.name) .toString(); } } 

Kode yang paling menarik dari perspektif entri blog ini ada di kelas di atas, terutama dalam metode equals () dan hashCode () . Daftar kode berikutnya mencantumkan kelas "tes" yang menggunakan kelas data sederhana yang ditentukan di atas baik dalam ArrayList dan HashSet, bergantung pada argumen baris perintah yang diberikan ke metode main (). Ini menunjukkan CLI Commons, tetapi yang lebih penting menunjukkan penggunaan metode equals () dan hashCode () di kelas data.