下面是正确的equals和Java中的hashCode实现吗?

时间:2014-03-10 09:53:15

标签: java hashcode

当一个对象的值相等时,我需要返回它是真的。

例如

@Override
public int hashCode() {
return new HashCodeBuilder().append(value).toHashCode();
}

@Override
public boolean equals(final Object obj) {
if (obj instanceof NumberValTO) {
  final NumberValTO other = (NumberVal) obj;
  return new EqualsBuilder().append(value, other.getValue()).isEquals();
}
return false;
}

以上是好还是错?

我在几个应用程序中看到,哈希码与表的每个字段都是多个,并且不确定它是否是正确的方法。

假设一个实体有4列 假设一个实体有2列

  1. 生成相同的最佳方法是哪种?
  2. 另外,我们是否需要为hibernate实体类实现hashcode()和equals()?
  3. 感谢。

3 个答案:

答案 0 :(得分:0)

您的示例很好,因为它提供了equals和hashcode方法的公平实现。我在我的项目中使用这种方式。

回答你1个问题你可以阅读http://www.ideyatech.com/2011/04/effective-java-equals-and-hashcode/

要回答你2个问题请点击链接:Hibernate: When is it necessary to implement equals() and hashCode(), and if so, how?

答案 1 :(得分:0)

是的,没关系,假设这些是您正在使用的Apache Commons帮助程序类。 @Vino是正确的,指出在if (obj == this) return true;方法的开头添加equals可能是值得优化的,但您的方法看起来是正确的。

答案 2 :(得分:0)

您的equalshashCode方法都正确地使用了Apache EqualsBuilder中的HashCodeBuildercommons-lang,但您应该添加引用检查 - {{ 1}} - 到if (obj == this) return true方法。

我最近反对使用EqualsBuilderHashCodeBuilder的论点是性能较差,所以我对其进行了测试。

我创建了一个equals,添加了10K条目,然后比较了同一个关键对象的查找时间,一次使用传统的HashMapequals,然后又使用{ {3}}和EqualsBuilder。我们的想法是,通过密钥获取值将会对hashCodeequals方法产生影响,并对其性能进行良好比较。

虽然HashCodeBuilderEqualsBuilder实施较慢,但差异在60ns范围内,HashCodeBuilder实施的平均查找时间约为320ns,而传统方法(我已经展示了我在下面使用的代码)。

恕我直言,这种性能损失只应该是一个问题,hashCodeequals在大量对象上被重复调用,即使这样,只有在小的性能增益值得牺牲清晰度的情况下你编码。

无论如何,这是我用来测试性能差异的类:

hashCode

这是测试:

public class Example
{
  private Type operationType;
  private long identity;
  private String name;
  private BigDecimal value;

  public Example(Type operationType, long identity, String name, BigDecimal value)
  {
    this.operationType = operationType;
    this.identity = identity;
    this.name = name;
    this.value = value;
  }

  public Example(Example example)
  {
    this.operationType = example.operationType;
    this.identity = example.identity;
    this.name = example.name;
    this.value = example.value;
  }

  public long getIdentity()
  {
    return identity;
  }

  public String getName()
  {
    return name;
  }

  public BigDecimal getValue()
  {
    return value;
  }

  @Override
  public boolean equals(Object obj)
  {
    if (Type.TRADITIONAL.equals(operationType))
    {
      if (this == obj)
      {
        return true;
      }
      if (obj == null || getClass() != obj.getClass())
      {
        return false;
      }

      Example example = (Example)obj;
      return getIdentity() == example.getIdentity()
        && ((getName() == null && example.getName() == null) || getName().equals(example.getName ()))
        && ((getValue() == null && example.getValue() == null) || getValue().equals(example.getValue()));
    }
    else
    {
      return this == obj || obj instanceof Example &&
        new EqualsBuilder()
          .append(getIdentity(), ((Example)obj).getIdentity())
          .append(getName(), ((Example)obj).getName())
          .append(getValue(), ((Example)obj).getValue())
          .isEquals();
    }
  }

  @Override
  public int hashCode()
  {
    if (Type.TRADITIONAL.equals(operationType))
    {
      int result = (int)(getIdentity() ^ (getIdentity() >>> 32));
      result = 31 * result + (getName() != null ? getName().hashCode() : 0);
      result = 31 * result + (getValue() != null ? getValue().hashCode() : 0);
      return result;
    }
    else
    {
      return new HashCodeBuilder().append(getIdentity()).append(getName()).append(getValue()).toHashCode();
    }
  }

  public static enum Type
  {
    TRADITIONAL,
    COMMONS
  }
}