来自一个字段的Java hashCode

Ins*_*ere 6 java hashcode

编辑:准备我的对象以便在HashMap中使用.

在阅读了一下如何生成哈希码之后,我现在很困惑.我的(可能是微不足道的)问题是,当我有一个可以使用的字段时,我应该如何实现hashCode方法?我可以直接使用fiels吗?如果我理解正确的话,hashCode的值在对象的生命周期内不能改变,我只有一个适合这个的ID,但是我已经在其他地方读过,那个人不应该使用ID ...这个怎么样,怎么样一个基于这个(唯一且没有变化)值的hashCode函数会是什么样的?equals方法也仅基于id ..

pol*_*nts 16

如果您的对象是可变的,则可以随时更改其哈希代码.当然,您应该更喜欢不可变对象(Effective Java第2版,第15项:最小化可变性).

以下是来自Effective Java 2nd Edition的hashCodeequals Josh Bloch的哈​​希码配方,第9项:覆盖始终覆盖:

有效的Java第二版哈希码配方

  • 在一个int名为的变量中存储一些常量非零值,比如17 result.
  • 计算每个字段的int哈希码c:
    • 如果该字段是a boolean,则计算(f ? 1 : 0)
    • 如果该字段是a byte, char, short, int,则计算(int) f
    • 如果该字段是a long,则计算(int) (f ^ (f >>> 32))
    • 如果该字段是a float,则计算Float.floatToIntBits(f)
    • 如果该字段是a double,则计算Double.doubleToLongBits(f),然后long如上所述对结果进行散列.
    • 如果该字段是一个对象引用,并且该类的equals方法通过递归调用来比较该字段equals,则hashCode在该字段上递归调用.如果该字段的值为null,则返回0.
    • 如果该字段是数组,则将其视为每个元素都是单独的字段.如果数组字段中的每个元素都很重要,则可以使用Arrays.hashCode版本1.5中添加的方法之一.
  • 将哈希码组合cresult如下:result = 31 * result + c;

按照原样配方是正确的,即使只有一个字段.只需根据字段的类型执行相应的操作.

请注意,有些库实际上可以为您简化,例如HashCodeBuilder来自Apache Commons Lang,或者只是Arrays.hashCode/deepHashCode来自java.util.Arrays.

这些库允许您简单地编写如下内容:

@Override public int hashCode() {
    return Arrays.hashCode(new Object[] {
        field1, field2, field3, //...
    });
}
Run Code Online (Sandbox Code Playgroud)

Apache Commons Lang的例子

下面是使用Apache的共享郎建设者,以促进便利性和可读性的一个更完整的例子equals,hashCode,toString,和compareTo:

import org.apache.commons.lang.builder.*;

public class CustomType implements Comparable<CustomType> {
    // constructors, etc
    // let's say that the "significant" fields are field1, field2, field3
    @Override public String toString() {
        return new ToStringBuilder(this)
            .append("field1", field1)
            .append("field2", field2)
            .append("field3", field3)
                .toString();
    }
    @Override public boolean equals(Object o) {
        if (o == this) { return true; }
        if (!(o instanceof CustomType)) { return false; }
        CustomType other = (CustomType) o;
        return new EqualsBuilder()
            .append(this.field1, other.field1)
            .append(this.field2, other.field2)
            .append(this.field3, other.field3)
                .isEquals();
    }
    @Override public int hashCode() {
        return new HashCodeBuilder(17, 37)
            .append(field1)
            .append(field2)
            .append(field3)
                .toHashCode();
    }
    @Override public int compareTo(CustomType other) {
        return new CompareToBuilder()
            .append(this.field1, other.field1)
            .append(this.field2, other.field2)
            .append(this.field3, other.field3)
                .toComparison();
    }
}
Run Code Online (Sandbox Code Playgroud)

编写这四种方法非常繁琐,并且很难确保所有合同都得到遵守,但幸运的是,图书馆至少可以帮助您轻松完成工作.某些IDE(例如Eclipse)也可以自动为您生成其中一些方法.

也可以看看

  • 从Java SE 7开始,您可以使用[Objects#hash(Object ...)](http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html#hash(java. lang.Object ...)). (3认同)