簡體   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