2013-06-08 10 views
17

Nehmen wir an, ich habe Klasse User:Ist es angemessen, dass equals() nur von einer ID abhängt?

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

Ist es richtig, die equals Methode außer Kraft zu setzen wie folgt?

@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; 
} 

Es stellt sich heraus, dass die Einzigartigkeit eines Objekts nur durch seine ID bestimmt wird. Aber in meiner Anwendung ist id immer eindeutig. Es ist in der Datenbank zur Verfügung gestellt. Ist meine equals Implementierung kompetent genug, um dies zu erklären? Oder ist das nicht die beste Vorgehensweise?

Natürlich verstehe ich, dass in diesem Fall die hashCode Umsetzung der folgenden sein sollte:

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

Was brauchen Sie '.equals()' für, wenn überhaupt? – fge

+0

Es sieht aus wie du bist gut. Wenn das Objekt gleich ist, wenn die IDs gleich sind, haben Sie den richtigen Code. – greedybuddha

+2

Bevor ein 'Benutzer' beibehalten wird, kann' id' null sein und dann wird 'equals' geworfen. Aber das ist nur eine Warze. Ich habe dein Muster oft gesehen. Eine SO-Frage führte zu diesem Teil der Hibernate-Dokumentation, die für Sie keine Rolle spielt: http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html/persistent-classes.html#persistent- Klassen-Equalshashcode –

Antwort

0

Es ist in Ordnung. Solange keine zwei verschiedenen Benutzer dieselbe ID haben können, ist Ihre equals Funktion ausreichend. Es kann ein Problem geben, wenn ein Benutzer zweimal (aus welchen Gründen auch immer) mit einer anderen ID dargestellt werden kann und Sie diese als gleich betrachten möchten.

0

Ihre equals() Methode dosen't wie es aussieht von IDE erzeugt wurde, da es nicht für 'id' Null-Wert überprüft, wie durch @Eric angegeben ..

das ist, was mein equals()/hashCode() Methode sah aus wie mit derselben 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; 
} 

wir immer die automatische Generierung für Standardcode, wo möglich verwenden sollte, da es viel weniger fehleranfällig ist.

auch, in Bezug auf Ihren Punkt in Bezug auf die Einzigartigkeit von 'ID' prop, das hängt von Ihrer Vorliebe und wie Sie Sie verwenden möchten equals-Methode (Geschäftsanforderung) dh wenn zwei Benutzernamen gleich sind, sind sie beim Vergleich gleich zwei Benutzerobjekte später ..

4

Ob Sie dies tun sollten, hängt von der Semantik Ihrer Klasse ab. Das heißt, was bedeutet es bedeutet zu sagen, dass zwei Objekte Ihrer Klasse gleichwertig sind? Der wichtigste Unterschied besteht zwischen Objekten mit Wertesemantik und Objekten mit Entitätssemantik. Entitätsobjekte sind nicht äquivalent, selbst wenn sie äquivalente Attribute (Farbe, Länge usw.) haben. In vielen Fällen, auch wenn das Objekt aus einer Datenbanktabelle mit einem Primärschlüssel gelesen wurde, haben Entitätsobjekte ein ID-Feld, das eindeutig ist. Vergleichen Sie nur das ID-Feld in diesem Fall ist das Richtige zu tun.

+0

sein. Wenn ein 'User' Objekt die Eigenschaften einiger Benutzer darstellt eine Datenbank, sollte es möglich sein, dass mehrere Objekte gleichzeitig für eine bestimmte ID existieren? Es scheint, dass es aus Gründen der Konsistenz besser wäre, alle derartigen Objekte durch eine Factory-Methode zu konstruieren, die eine Art Sammlung mit schwachem Bezug verwendet, um sicherzustellen, dass, solange irgendein Bezug auf einen "Benutzer" mit irgendeiner ID besteht um einen 'Benutzer' mit dieser ID zu erhalten, wird dasselbe Objekt zurückgegeben. Wenn das getan ist, wird es nicht nötig sein, dass "Benutzer" 'gleich 'überschreibt. – supercat

0

Es ist in Ordnung, ID für equals Methode zu verwenden, solange Sie eine Entität nicht vergleichen müssen, die noch nicht an die DB persistent war. Wenn Sie Entitäten vergleichen möchten, die noch nicht gespeichert wurden, müssen Sie ihre Attribute vergleichen.

0

Ich stimme zu, es ist auf der ID. Aber ich hatte Probleme beim Abrufen von Daten, die die Datenbank aktualisieren sollten. Mit diesem Beispiel mit User wo gleich nur auf ID geschaut wurde habe ich diese erstellt.

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

Mit diesem können wir dies haben.

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

Dann können wir dies tun

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

Stimmen Sie zu, dies ein Weg, dies zu tun ist. ??????