1

我想尝试在我正在创建的大量对象上覆盖 equals/hashCode,并使用 Java 1.7 开发一个接口/实用程序类来执行此操作。由于我不确定这种方法将如何执行,我将不胜感激任何反馈。我主要关心的是使用原始类型的自动装箱以及我将采取什么样的性能影响。

界面:

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();
}

实用程序类:

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();
    }
}
4

1 回答 1

6

相信我。不要写你自己的散列/等于逻辑。

使用已经可用且经过测试的代码,例如 Apache EqualsBuilderHashCodeBuilder

例如:

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();
  }
于 2012-10-05T16:10:44.787 回答