equals()仅依赖于ID是否合适?

时间:2013-06-08 20:16:19

标签: java oop override equals hashcode

我们假设我有课User

public class User {
  private Long id;
  private String name;
  private Integer age;
  private BigDecimal account;
  // other fields, getters and setters
}

如下覆盖equals方法是否合适?

@Override
public boolean equals(Object ob) {
   if (ob == null) {
       return false;
   }
   if (this == ob) {
       return true;
   }
   if (ob instanceof User) {
       User other = (User) ob;
       return this.id.equals(other.getId());
   }
   return false;
}

事实证明,对象的唯一性仅由其ID决定。但在我的应用程序中,id始终是唯一的。它在数据库中提供。我的equals实施是否足以说明这一点?或者这不是最佳做法吗?

我当然理解,在这种情况下,hashCode实现应该如下:

@Override
public int hashCode() {
   return id.intValue();
}

5 个答案:

答案 0 :(得分:7)

是否应该这样做取决于你班级的语义。也就是说,意味着什么来说你的班级的两个对象是等价的?最重要的区别在于具有值语义的对象和具有实体语义的对象之间。实体对象即使具有相同的属性(颜色,长度等)也不相等。在许多情况下,包括从具有主键的数据库表中读取对象时,实体对象将具有唯一的ID字段。在这种情况下仅比较ID字段是正确的事情。

答案 1 :(得分:0)

没关系。只要没有两个不同的用户可以拥有相同的ID,您的equals功能就足够了。如果一个用户可以使用不同的ID(无论出于何种原因)两次表示,并且您确实希望将它们视为相等,则可能会出现问题。

答案 2 :(得分:0)

你的equals()方法看起来不像它是由IDE生成的,因为它没有检查@Eric所声明的'id'null值。

这就是我的equals()/ hashCode()方法看起来像使用相同的id prop

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    User11 other = (User11) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    } else if (!id.equals(other.id))
        return false;
    return true;
}

我们应该尽可能使用自动生成样板代码,因为它更不容易出错。

另外,关于你关于'id'道具的唯一性的观点,这取决于你的偏好以及你想如何使用你等于方法(业务要求),即如果两个用户的名字相同,那么当比较两个时,它们被认为是相同的用户对象稍后..

答案 3 :(得分:0)

只要您不必将尚未保留的实体与数据库进行比较,就可以使用equals方法的id。如果您想比较尚未保存的实体,则必须比较它们的属性。

答案 4 :(得分:0)

我同意这是id。 但是在获取应该更新数据库的数据时我遇到了麻烦。 使用User的这个例子,其中equals只查看ID我创建了这个。

interface DataEquals<T extends DataEquals> {
   public boolean isDataEquals(T other)
}


User implements DataEquals<User> {
   public boolean isDataEquals(User other) {
      boolean b1 = getName().equals(other.getName());
      boolean b2 = getAge().equals(other.getAge());
      boolean b3 = getAccount().equals(other.getAccount());
      return b1 && b2 && b3;
   }
}

有了这个我们可以拥有这个。

public class ListChanges<T extends DataEquals<T>> {

  private List<T> added = new ArrayList<T>();
  private List<T> removed = new ArrayList<T>();
  private List<T> changed = new ArrayList<T>();
  private List<T> unchanged = new ArrayList<T>();

  public ListChanges() {
    super();
  }
  public List<T> getAdded() {
    return added;
  }
  public List<T> getChanged() {
    return changed;
  }
  public List<T> getRemoved() {
    return removed;
  }
  public List<T> getUnchanged() {
    return unchanged;
  }

  public boolean hasAnyChanges() {
    return added.size()>0 || removed.size()>0 || changed.size()>0;
  }

  public void parse(List<T> oldList,List<T> newList) {
    for (T oldObj : oldList) {
        int index =newList.indexOf(oldObj);
        if (index==-1) {
            removed.add(oldObj);
        } else {
            T newObj = newList.get(index);

            if (newObj.isDataEquals(oldObj)) {
                unchanged.add(oldObj);
            } else {
                changed.add(newObj);
            }
        }
    }
    for (T newObj : newList) {
        if (oldList.indexOf(newObj)==-1) {
            added.add(newObj);
        }
    }
 }
}

然后我们可以这样做

List<User> oldList = ....;
List<User> newList = ...;
ListChanges<User> listChanges = new ListChanges<User>();
listChanges.parseChanges(oldList,newList);

你是否同意这是一种方法。 ??????