比较具有大量属性的两个类实例

时间:2018-04-13 18:41:36

标签: java hash equals

我有一个超过30个属性的类。

我想覆盖equals方法,以便比较我的类的两个实例。

但是我想避免在我的方法中重写所有30个属性

@Override
public boolean equals(java.lang.Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    Address address = (Address) o;
    return Objects.equals(this.attr1, address.attr1) &&
            Objects.equals(this.attr2, address.attr2) &&
            Objects.equals(this.attr3, address.attr3) &&
            ......
            Objects.equals(this.attr30, address.attr30);

}

你有一个更简单和正确的方法吗?

5 个答案:

答案 0 :(得分:2)

你在apache commons库中有这个方法,它使用反射来比较它们

org.apache.commons.lang.builder.EqualsBuilder.reflectionEquals(Object, Object)

实施例

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

public class MyObject {

   ...
   @Override
   public boolean equals(Object obj) {
      return EqualsBuilder.reflectionEquals(this, obj);
  }
}

答案 1 :(得分:2)

您可以使用lombok项目在构建时自动生成hashCode和equals方法。

答案 2 :(得分:2)

您可以使用Field包中的java.lang.reflect类,如下所示:

@Override
public boolean equals(Object o) {
    //instanceof check, null check, etc

    Field[] fields = Address.class.getDeclaredFields();

    for (Field field : fields) {
        try {
            field.setAccessible(true);

            if (!field.get(this).equals(field.get((Address) o))) {
                return false;
            } //end if
        } catch (IllegalAccessException e) {
            //handle exception
        } //end try catch
    } //end for

    return true;
} //equals

答案 3 :(得分:2)

嗯,这基本上是必要的样板代码类型。幸运的是,有很多开发人员对编写此类代码感到恼火。出于这样的原因,Project Lombok成立了。

see this link.

例如,请参阅我在上面链接的页面中提取的以下两个代码段:

<强>龙目

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(exclude={"id", "shape"})
public class EqualsAndHashCodeExample {
  private transient int transientVar = 10;
  private String name;
  private double score;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  private int id;

  public String getName() {
    return this.name;
  }

  @EqualsAndHashCode(callSuper=true)
  public static class Square extends Shape {
    private final int width, height;

    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }
}

Vanilla Java

import java.util.Arrays;

public class EqualsAndHashCodeExample {
  private transient int transientVar = 10;
  private String name;
  private double score;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  private int id;

  public String getName() {
    return this.name;
  }

  @Override public boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof EqualsAndHashCodeExample)) return false;
    EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
    if (!other.canEqual((Object)this)) return false;
    if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
    if (Double.compare(this.score, other.score) != 0) return false;
    if (!Arrays.deepEquals(this.tags, other.tags)) return false;
    return true;
  }

  @Override public int hashCode() {
    final int PRIME = 59;
    int result = 1;
    final long temp1 = Double.doubleToLongBits(this.score);
    result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
    result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
    result = (result*PRIME) + Arrays.deepHashCode(this.tags);
    return result;
  }

  protected boolean canEqual(Object other) {
    return other instanceof EqualsAndHashCodeExample;
  }

  public static class Square extends Shape {
    private final int width, height;

    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }

    @Override public boolean equals(Object o) {
      if (o == this) return true;
      if (!(o instanceof Square)) return false;
      Square other = (Square) o;
      if (!other.canEqual((Object)this)) return false;
      if (!super.equals(o)) return false;
      if (this.width != other.width) return false;
      if (this.height != other.height) return false;
      return true;
    }

    @Override public int hashCode() {
      final int PRIME = 59;
      int result = 1;
      result = (result*PRIME) + super.hashCode();
      result = (result*PRIME) + this.width;
      result = (result*PRIME) + this.height;
      return result;
    }

    protected boolean canEqual(Object other) {
      return other instanceof Square;
    }
  }
}

如果您喜欢这种方法,我建议您完整地查看Project Lombok。它真的有助于清理你的代码!

<强> !!!小心!!! 为了能够实际使用Lombok生成的方法,您需要将Lombok插件安装到IDE中!否则,您的IDE不会知道自动生成的方法。

答案 4 :(得分:1)

您可以使用单位http://www.unitils.org/cookbook.html

import static org.unitils.reflectionassert.ReflectionAssert.*;
// Exact field-by-field comparison
assertReflectionEquals(new Person("John", "Doe", new Address("New street", 5, "Brussels")), 
                             new Person("John", "Doe", new Address("New street", 5, "Brussels"));