Die Commons / Lang-Builder sind großartig und ich benutze sie seit Jahren ohne merklichen Leistungsaufwand (mit und ohne Ruhezustand). Aber wie Alain schreibt, ist der Guavenweg noch schöner:
Hier ist ein Beispiel Bean:
public class Bean{
private String name;
private int length;
private List<Bean> children;
}
Hier sind equals () und hashCode (), die mit Commons / Lang implementiert wurden:
@Override
public int hashCode(){
return new HashCodeBuilder()
.append(name)
.append(length)
.append(children)
.toHashCode();
}
@Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return new EqualsBuilder()
.append(name, other.name)
.append(length, other.length)
.append(children, other.children)
.isEquals();
} else{
return false;
}
}
und hier mit Java 7 oder höher (inspiriert von Guava):
@Override
public int hashCode(){
return Objects.hash(name, length, children);
}
@Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return Objects.equals(name, other.name)
&& length == other.length // special handling for primitives
&& Objects.equals(children, other.children);
} else{
return false;
}
}
Hinweis: Dieser Code bezog sich ursprünglich auf Guava. Wie in Kommentaren bereits erwähnt, wurde diese Funktionalität inzwischen im JDK eingeführt, sodass Guava nicht mehr benötigt wird.
Wie Sie sehen, ist die Guava / JDK-Version kürzer und vermeidet überflüssige Hilfsobjekte. Bei Gleichheit kann die Auswertung sogar kurzgeschlossen werden, wenn ein früherer Object.equals()
Aufruf false zurückgibt (um fair zu sein: commons / lang hat eine ObjectUtils.equals(obj1, obj2)
Methode mit identischer Semantik, die anstelle von verwendet werden könnteEqualsBuilder
wie oben einen Kurzschluss zuzulassen).
Also: Ja, die Commons Lang Builder sind gegenüber manuell erstellten equals()
und sehr vorzuziehenhashCode()
Methoden Methoden (oder diesen schrecklichen Monstern, die Eclipse für Sie generiert) , aber die Java 7+ / Guava-Versionen sind noch besser.
Und ein Hinweis zu Hibernate:
Seien Sie vorsichtig bei der Verwendung von Lazy Collections in Ihren Implementierungen equals (), hashCode () und toString (). Das wird kläglich scheitern, wenn Sie keine offene Sitzung haben.
Hinweis (ungefähr gleich ()):
a) In beiden Versionen von equals () oben möchten Sie möglicherweise auch eine oder beide dieser Verknüpfungen verwenden:
@Override
public boolean equals(final Object obj){
if(obj == this) return true; // test for reference equality
if(obj == null) return false; // test for null
// continue as above
b) Abhängig von Ihrer Interpretation des equals () - Vertrags können Sie auch die Zeile (n) ändern.
if(obj instanceof Bean){
zu
// make sure you run a null check before this
if(obj.getClass() == getClass()){
Wenn Sie die zweite Version verwenden, möchten Sie wahrscheinlich auch super(equals())
Ihre equals()
Methode aufrufen . Die Meinungen sind hier unterschiedlich, das Thema wird in dieser Frage diskutiert:
richtiger Weg, um Superklasse in eine Implementierung von Guava Objects.hashcode () zu integrieren?
(obwohl es darum geht hashCode()
, gilt das gleiche für equals()
)
Hinweis (inspiriert von Kommentar von Kayahr )
Objects.hashCode(..)
(genau wie der Basiswert Arrays.hashCode(...)
) kann schlecht funktionieren, wenn Sie viele primitive Felder haben. In solchen Fällen EqualsBuilder
kann tatsächlich die bessere Lösung sein.
reflectionEquals
undreflectionHashcode
Funktionen verführen. Die Leistung ist ein absoluter Killer.