/ を実装するためにorg.apache.commons.lang.builder
EqualsBuilder
/を使用することについて、ここでの皆さんがどう考えているか知りたいです。自分で書くよりも良い方法でしょうか? Hibernate とうまく連携しますか? あなたの意見は?HashCodeBuilder
equals
hashCode
ベストアンサー1
commons/lang ビルダーは素晴らしいので、私は何年も使用していますが、パフォーマンスのオーバーヘッドは目立ったことはありません (休止状態の有無にかかわらず)。しかし、Alain が書いているように、Guava の方法はさらに優れています。
サンプルの Bean は次のとおりです。
public class Bean{
private String name;
private int length;
private List<Bean> children;
}
Commons/Lang で実装された equals() と hashCode() は次のとおりです。
@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;
}
}
Java 7 以降の場合 (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;
}
}
注: このコードは元々 Guava を参照していましたが、コメントで指摘されているように、この機能はその後 JDK に導入されたため、Guava は不要になりました。
ご覧のとおり、Guava / JDK バージョンは短く、余分なヘルパー オブジェクトを回避します。equals の場合、以前のObject.equals()
呼び出しが false を返した場合に評価を短絡することもできます (公平を期すために、commons / lang には、上記の短絡を許可するObjectUtils.equals(obj1, obj2)
代わりに使用できる、同一のセマンティクスを持つメソッドがあります)。EqualsBuilder
つまり、確かに、Commons 言語ビルダーは手動で構築されたメソッド (または Eclipse が生成するひどいモンスター) よりも非常に優れていますがequals()
、hashCode()
Java 7+ / Guava バージョンはさらに優れています。
Hibernate についての注意:
equals()、hashCode()、toString() の実装で遅延コレクションを使用する場合は注意してください。開いているセッションがない場合、これは失敗します。
注意 (equals() について):
a) 上記の equals() の両方のバージョンで、次のショートカットの 1 つまたは両方を使用することもできます。
@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) equals() 契約の解釈によっては、次の行も変更する必要があるかもしれません。
if(obj instanceof Bean){
に
// make sure you run a null check before this
if(obj.getClass() == getClass()){
super(equals())
2 番目のバージョンを使用する場合は、メソッド内でも呼び出す必要があるでしょうequals()
。この点については意見が分かれており、このトピックについては次の質問で議論されています。
( については ですがhashCode()
、 についても同様ですequals()
)
メモ(コメントからインスピレーションを受けたカヤール)
Objects.hashCode(..)
(基礎となる と同様にArrays.hashCode(...)
)は、プリミティブ フィールドが多数ある場合はパフォーマンスが低下する可能性があります。そのような場合は、 の方がEqualsBuilder
実際にはより適切なソリューションである可能性があります。