2013-06-08 9 views
17

Давайте предположим, что у меня есть класс User:Правильно ли для equals() зависит только от идентификатора?

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 всегда уникален. Он предоставляется в базе данных. Является ли моя реализация equals достаточно компетентной, чтобы учесть это? Или это не лучшая практика?

Конечно, я понимаю, что в этом случае hashCode реализация должна быть следующей:

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

Что вам нужно? .Equals() 'для чего-нибудь? – fge

+0

Похоже, вы добры. Если объект равен, когда идентификаторы равны, у вас есть правильный код. – greedybuddha

+2

Прежде чем 'User' будет сохранен,' id' может быть нулевым, а затем 'equals' будет бросать. Но это просто бородавка. Я часто видел ваш узор. Один из вопросов SO привел к этому документу Hibernate, который может не иметь для вас значения: http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html/persistent-classes.html#persistent- classes-equalshashcode –

ответ

0

Это нормально. До тех пор, пока у двух разных пользователей не будет одинакового идентификатора, достаточно вашей функции equals. Может возникнуть проблема, если один пользователь может быть представлен дважды с другим ID (по любой причине), и вы хотите считать их равными.

0

ваши равно() метод dosen't выглядеть он был сгенерирован IDE, как он не проверяет «ид» нулевое значение, как указано на @Eric ..

это то, что мои Equals()/метод хэш-код() выглядел как, используя тот же идентификатор проп

@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» prop, которая зависит от ваших предпочтений и того, как вы хотите использовать метод equals (бизнес-требование), т.е. если два имени пользователя одинаковы, они должны считаться одинаковыми при сравнении два пользовательских объекта позже ..

4

Независимо от того, следует ли это делать, это зависит от семантики вашего класса. То есть, что означает означает, чтобы сказать, что два объекта вашего класса эквивалентны? Самое важное отличие - это объекты с семантикой значений и объекты с семантикой сущности. Объекты Entity не эквивалентны, даже если они имеют эквивалентные атрибуты (цвет, длина и т. Д.). Во многих случаях, в том числе, когда объект был прочитан из таблицы базы данных с первичным ключом, объекты объекта будут иметь уникальное поле идентификатора. Сравнивая только поле ID в этом случае, это правильная вещь.

+0

Если объект' User' представляет характеристики некоторого пользователя в базы данных, должно ли возможно, чтобы более одного такого объекта существовало одновременно для любого данного идентификатора? Казалось бы, для согласованности было бы лучше, чтобы все такие объекты были построены с помощью фабричного метода, который использует какую-то коллекцию с слабой ссылкой, чтобы гарантировать, что до тех пор, пока какая-либо ссылка существует для «Пользователя» с некоторым идентификатором, любые запросы для получения «User» с этим идентификатором будет возвращен один и тот же объект. Если это будет сделано, не будет необходимости в 'User' переопределять' equals'. – supercat

0

Это нормально использовать идентификатор для метода equals, если вам не нужно сравнивать объект, который еще не был сохранен в БД. Если вы хотите сравнить объекты, которые еще не были сохранены, вам придется сравнить их атрибуты.

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); 

Вы согласны с тем, что это способ сделать это. ??????

Смежные вопросы