Это наивный равный, hashcode OK?

у меня есть класс, представляющий DB-записи с уникальным атрибутом Id. Is нормально реализовать equals() и hashcode() методы, основанные только на этот атрибут

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

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

4 ответов


В общем, да. Если все идентификаторы являются небольшими последовательными целыми числами, вы можете получить лучшую производительность из больших коллекций, используя функцию, которая распределяет биты более широко по доступным 32 битам. Но это должно работать иначе.


Я не вижу ничего плохого в этом коде. Тем не менее, есть некоторые вопросы, которые вы могли бы подумать:

  • можете ли вы когда-нибудь иметь более одного объекта с тем же id?
  • будет ли класс когда-либо подклассом?

проблема с использованием id для установления равенства заключается в том, что вы можете сравнить объекты, которым еще не присвоен id, с объектами, имеющими ID. В этом случае методы equals и hashCode должны использовать бизнес-поля, которые делают объект уникальным ("бизнес-ключ").

также сравнение класса вместо использования instanceof исключает подклассы, как говорит NPE.

этот код терпим, это не мой предпочтительный способ делать вещи. По той простой случаи, когда это перебор, методы hashCode и equals, определенные Object, выполнят работу. Для более продвинутых моделей доменов это неадекватно, потому что подклассы и сравнения по бизнес-ключу действительно будут полезны.


Вы сказали в своих комментариях, что класс является окончательным, тогда я бы предложил равный дизайн, как в Integer.равно

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}