1. ホーム
  2. java

[解決済み] Apache Commons equals/hashCode builder [終了しました]。

2022-04-25 01:50:28

質問

を使うことについてどう思うか、知りたいと思っています。 org.apache.commons.lang.builder EqualsBuilder / HashCodeBuilder を実装するためのものです。 equals / hashCode ? 自分で書くより良い方法でしょうか?Hibernateと相性が良いのか?あなたの意見はどうですか?

どのように解決するのですか?

コモンズ/ラングビルダーは素晴らしく、私は何年も使っていますが、目立ったパフォーマンスのオーバーヘッドもありません(ハイバーネートの有無にかかわらず)。しかし、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バージョンはより短く、余分なヘルパーオブジェクトを避けることができます。等号の場合、もし以前の Object.equals() の呼び出しはfalseを返します(公平を期すため、commons / langには ObjectUtils.equals(obj1, obj2) メソッドの代わりに使用することができます。 EqualsBuilder を使えば、上記のような短絡的な操作が可能になります)。

そうです、コモンズの言語ビルダーは、手動で構築された equals()hashCode() メソッド(またはEclipseが生成するひどいモンスター)がありますが、Java 7+ / Guavaのバージョンはさらに優れています。

そして、Hibernateについての注意点です。

equals()、hashCode()、toString()の実装で遅延コレクションを使用することに注意してください。もし、Sessionを開いていないなら、それは惨めに失敗するでしょう。


注意(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()){ 

2番目のバージョンを使用する場合は、おそらく super(equals()) の内部で equals() メソッドを使用します。ここでは意見が分かれますが、このトピックはこの質問で議論されています。

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

(についてですが)。 hashCode() にも適用されます。 equals() )


注釈 (コメント欄から着想を得ています) カヤール )

Objects.hashCode(..) (ちょうど、その下の Arrays.hashCode(...) ) は、多くのプリミティブ・フィールドを持つ場合、パフォーマンスが悪くなる可能性があります。そのような場合は EqualsBuilder は、実際にはより良い解決策である可能性があります。