繁体   English   中英

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

[英]Is the below is correct equals and hashCode implementation in Java?

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

@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. 另外,我们是否需要为休眠实体类实现hashcode()和equals()?

谢谢。

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

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

要回答2个问题,请点击以下链接: 休眠:什么时候需要实现equals()和hashCode(),如果需要,如何实现?

是的,这很好,假设这些是您正在使用的Apache Commons帮助器类。 @Vino是正确的,指出添加if (obj == this) return true; equals方法的开始可能是一个值得优化的方法,但是您的方法看起来仍然正确。

您的equalshashCode方法都正确地使用了Apache commons-langEqualsBuilderHashCodeBuilder ,尽管您应该向equals方法添加引用检查- if (obj == this) return true equals

我最近被反对使用EqualsBuilderHashCodeBuilder的一个论据是它的性能较差,因此我对其进行了测试。

我创建了一个HashMap ,添加了1万个条目,然后比较了相同键对象的查找时间,一次使用了传统的equalshashCode ,然后再次使用了EqualsBuilderHashCodeBuilder 想法是,通过键获取值将锤击equalshashCode方法,并对其性能进行良好的比较。

尽管EqualsBuilderHashCodeBuilder实现的速度较慢,但​​差异在60ns左右, commons-lang实现的平均查找时间约为320ns,传统方法的平均查找时间为260ns(我在下面展示了我使用的代码) 。

恕我直言,只有在大量对象上反复调用equalshashCode情况下,才应该考虑这种性能损失,即使在这种情况下,只有很小的性能提升就值得牺牲代码的清晰度。

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

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
  }
}

这是测试:

public class ExampleTest
{
  @Test
  public void testMapLookupWithTraditional() throws Exception
  {
    double total = 0;

    for (int i = 0; i < 10; i++)
    {
      total += testMapLookup(Example.Type.TRADITIONAL);
    }

    System.out.println("Overall Average: " + (total / 10));
  }

  @Test
  public void testMapLookupWithCommons() throws Exception
  {
    double total = 0;

    for (int i = 0; i < 10; i++)
    {
      total += testMapLookup(Example.Type.COMMONS);
    }

    System.out.println("Overall Average: " + (total / 10));
  }

  private double testMapLookup(Example.Type operationType) throws Exception
  {
    Map<Example, String> examples = new HashMap<Example, String>();

    while (examples.size() < 10000)
    {
      long now = System.currentTimeMillis();

      Example example = new Example(
        operationType,
        now,
        "EXAMPLE_" + now,
        new BigDecimal(now)
      );

      examples.put(example, example.getName());
      Thread.sleep(1);
    }

    int count = 0;
    double average = 0;
    double max = 0;
    double min = Double.MAX_VALUE;

    for (Example example : examples.keySet())
    {
      Example copiedExample = new Example(example);

      long start = System.nanoTime();

      examples.get(copiedExample);

      long duration = System.nanoTime() - start;

      average = ((average * count++) + duration) / count;

      if (max < duration) max = duration;
      if (min > duration) min = duration;
    }

    System.out.println("Average: " + average);
    System.out.println("Max: " + max);
    System.out.println("Min: " + min);

    return average;
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM