I have a thought on attempting to override equals/hashCode on a slew of objects I am creating and developing an interface/utility class for doing this using Java 1.7. Since I am unsure of how this approach will perform I would appreciate any feedback. My primary concern is using autoboxing with primitive types and what kind of performance hits I will take.
Interface:
public interface Hashable {
/**
* Return the base offset for the {@link Object#hashCode()}, this number
* should be unique and odd;
*
* @return int
*/
public int getBaseOffset();
/**
* Return the base offset for the class fields{@link Object#hashCode()},
* this number should be unique and odd;
*
* @return int
*/
public int getFieldOffset();
/**
* Return an {@link Object} array of the fields to use for
* {@link Object#equals(Object)} and {@link Object#hashCode()}
*
* @return {@link Object} array
*/
public Object[] getHashFields();
}
Utility Class:
public class HashUtil {
/**
* This method will create a hash code based on the
* {@link Hashable#getHashFields()}. If the object is immutable this method
* only needs to be called once through lazy initialization, otherwise the
* class can call out to it through the {@link Object#hashCode()} override.
* <p>
* <b>Example:</b>
*
* <pre>
* public int hashCode() {
* return HashUtil.createHash(this);
* }
* <p>
* @param hashable
* {@link Object} implementing {@link Hashable} interface
* @return int
* to use for hash code
*/
public static int createHash(Hashable hashable) {
HashCodeBuilder builder = new HashCodeBuilder(hashable.getBaseOffset(), hashable.getFieldOffset());
for (Object o : hashable.getHashFields()) {
if (o != null) {
builder.append(o);
}
}
return builder.toHashCode();
}
/**
* Evaluates whether two {@link Hashable} objects are equal. This method is
* intended for use when overriding {@link Object#equals(Object)}.
* <p>
* <b>Example:</b>
*
* <pre>
* public boolean equals(Object o) {
* return HashUtil.equals(this, o);
* }
* <p>
* @param h1 first {@link Hashable} to compare
* @param h2 second {@link Hashable} to compare
* @return true if they are equal
*/
public static boolean equals(Hashable h1, Hashable h2) {
if (h1.getHashFields() == null || h2.getHashFields() == null) {
if (!(h1.getHashFields() == null && h2.getHashFields() == null)) {
return false;
}
return true;
}
if (h1.getHashFields().length != h2.getHashFields().length) {
return false;
}
EqualsBuilder builder = new EqualsBuilder();
for (int x = 0; x < h1.getHashFields().length; x++) {
Object o1 = h1.getHashFields()[x];
Object o2 = h2.getHashFields()[x];
builder.append(o1, o2);
}
return builder.isEquals();
}
}
Trust me. Dont write you own hashing/equals logic.
Use already available and tested code like Apache EqualsBuilder and HashCodeBuilder
Eg:
public int hashCode() {
// you pick a hard-coded, randomly chosen, non-zero, odd number
// ideally different for each class
return new HashCodeBuilder(17, 37).
append(name).
append(age).
toHashCode();
}
public boolean equals(Object obj) {
// do you basic object check first
// then delegate to equalsbuilder
MyClass rhs = (MyClass) obj;
return new EqualsBuilder()
.append(name, rhs.name)
.append(age, rhs.age)
.isEquals();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.