Apache Commons equals/hashCode ビルダー [closed] 質問する

Apache Commons equals/hashCode ビルダー [closed] 質問する

/ を実装するためにorg.apache.commons.lang.builder EqualsBuilder/を使用することについて、ここでの皆さんがどう考えているか知りたいです。自分で書くよりも良い方法でしょうか? Hibernate とうまく連携しますか? あなたの意見は?HashCodeBuilderequalshashCode

ベストアンサー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()。この点については意見が分かれており、このトピックについては次の質問で議論されています。

スーパークラスを Guava Objects.hashcode() 実装に組み込む正しい方法は何ですか?

( については ですがhashCode()、 についても同様ですequals()


メモ(コメントからインスピレーションを受けたカヤール

Objects.hashCode(..)(基礎となる と同様にArrays.hashCode(...))は、プリミティブ フィールドが多数ある場合はパフォーマンスが低下する可能性があります。そのような場合は、 の方がEqualsBuilder実際にはより適切なソリューションである可能性があります。

おすすめ記事