Javaの2つのオブジェクトをnull値と比較します


189

Javaで2つの文字列が等しいかどうかを比較したいのですが、どちらかまたは両方がそうである場合null、単純にを呼び出すことはできません.equals()。最良の方法は何ですか?

boolean compare(String str1, String str2) {
    ...
}

編集:

return ((str1 == str2) || (str1 != null && str1.equals(str2)));

回答:


173

これは、Java内部コードが(他のcompareメソッドで)使用するものです。

public static boolean compare(String str1, String str2) {
    return (str1 == null ? str2 == null : str1.equals(str2));
}

3
文字列型を単にオブジェクトに変更しないでください-それをより一般的なものにしますか?そしてそれは、Java 7に移動した場合、あなたが得るものと同じである
トム・

3
あなたが提供したメソッドを含むJavaクラスはどれですか?
Volodymyr Levytskyi 14

30
おい!true / falseを返す比較メソッドは必要ありません。Equalsは、compareと同じではありません。ソートはソートに役立ちます。戻るか<0==0どちら>0が低いか大きいかを示す必要があります
coya

10
Objects.equals(Object, Object)Mark Rotteveelが彼の回答で指摘したように、使用することをお勧めします(投票してください)
Neuron

1
@Ericは、あまり良い答えにはなりません。最良の答えは常に、常に存在していたすべてのJavaバージョンと互換性のあるコードのみを含むものであると主張しないでしょう
Neuron

315

Java 7以降では、静的メソッドjava.util.Objects.equals(Object, Object)を使用して、2つのオブジェクトが等しいかどうかを気にすることなく、それらのオブジェクトに対して等価チェックを実行できますnull

両方のオブジェクトがnull存在する場合はそれが返されtrue、一方がそうnullでもう一方がそうでない場合はそれが返されfalseます。それ以外の場合equalsは、2番目を引数として最初のオブジェクトを呼び出した結果を返します。


このアプローチは、プログラムの実行時まで型チェックを延期します。2つの結果:実行時の速度が遅くなり、誤って異なるタイプを比較しようとしてもIDEから通知されません。
averasko

10
@averasko使用するObject.equals(Object)場合、コンパイル時の型チェックはありません。Objects.equals(Object, Object)非常に多く、通常と同じように機能しequals、そして再推論/ IDEによってチェックは、これらのルールはまたのためにサポートされている経験則ですObjects.equals(Object, Object)(例えばのIntelliJ IDEA 2016.2通常の等号とオブジェクトから1の両方に同じチェックを持っています)。
Mark Rotteveel 16

2
私はこのアプローチが好きです。最近、ApacheCommonsライブラリを含める必要はありません。
Torsten Ojaperv 2016

1
@SimonBaarsこれは、nullオブジェクトに対して関数を実行していません。これは、nullの2つの引数、またはオブジェクトへの参照を渡す静的メソッドです。
Mark Rotteveel 2017年

8
私見これは受け入れられる答えでなければなりません。Iすべての単一のアプリケーションのI書き込みに車輪の再発明をしたくない
ニューロン

45

これらの場合Apache Commons StringUtils#equalsを使用する方がよいでしょう。すでにnull文字列を処理しています。コードサンプル:

public boolean compare(String s1, String s2) {
    return StringUtils.equals(s1, s2);
}

ライブラリを追加したくない場合は、メソッドのソースコードをコピーして、StringUtils#equals必要なときに適用します。


28

Android 19でAPI 19のObjects.equals(str1、str2)を使用できない人のために、これがあります:

android.text.TextUtils.equals(str1, str2);

ヌルセーフです。Androidの同一の文字列は、Androidの文字列プーリングのおかげでほとんど常に「==」オペランドとtrueと比較されるため、より高価なstring.equals()メソッドを使用する必要はほとんどなく、長さチェックはほとんどの不一致をすばやく除外する方法です。

ソースコード:

/**
 * Returns true if a and b are equal, including if they are both null.
 * <p><i>Note: In platform versions 1.1 and earlier, this method only worked  well if
 * both the arguments were instances of String.</i></p>
 * @param a first CharSequence to check
 * @param b second CharSequence to check
 * @return true if a and b are equal
 */
public static boolean equals(CharSequence a, CharSequence b) {
    if (a == b) return true;
    int length;
    if (a != null && b != null && (length = a.length()) == b.length()) {
        if (a instanceof String && b instanceof String) {
            return a.equals(b);
        } else {
            for (int i = 0; i < length; i++) {
                if (a.charAt(i) != b.charAt(i)) return false;
            }
            return true;
        }
    }
    return false;
}

7

バージョン3.5以降、Apache Commons StringUtilsには次のメソッドがあります。

static int  compare(String str1, String str2)
static int  compare(String str1, String str2, boolean nullIsLess)
static int  compareIgnoreCase(String str1, String str2)
static int  compareIgnoreCase(String str1, String str2, boolean nullIsLess)

これらはnullセーフな文字列比較を提供します。


6

Java 8の使用

private static Comparator<String> nullSafeStringComparator = Comparator
        .nullsFirst(String::compareToIgnoreCase); 

private static Comparator<Metadata> metadataComparator = Comparator
        .comparing(Metadata::getName, nullSafeStringComparator)
        .thenComparing(Metadata::getValue, nullSafeStringComparator);

public int compareTo(Metadata that) {
    return metadataComparator.compare(this, that);
}

4

Apache Commons StringUtilsクラスのequals(-、-)およびequalsIgnoreCase(-、-)メソッドを使用して2つの文字列を比較します。

StringUtils.equals(-、-)

StringUtils.equals(null, null)   = true
StringUtils.equals(null, "abc")  = false
StringUtils.equals("abc", null)  = false
StringUtils.equals("abc", "abc") = true
StringUtils.equals("abc", "ABC") = false

StringUtils.equalsIgnoreCase( - 、 - )

StringUtils.equalsIgnoreCase(null, null)   = true
StringUtils.equalsIgnoreCase(null, "abc")  = false
StringUtils.equalsIgnoreCase("xyz", null)  = false
StringUtils.equalsIgnoreCase("xyz", "xyz") = true
StringUtils.equalsIgnoreCase("xyz", "XYZ") = true


2
boolean compare(String str1, String str2) {
    if(str1==null || str2==null) {
        //return false; if you assume null not equal to null
        return str1==str2;
    }
    return str1.equals(str2);
}

これはあなたが望んだことですか?


5
このケースはfalse、両方のストリングがnull望ましい結果ではない可能性がある場合に返されます。
JScoobyCed 2012年

1
boolean compare(String str1, String str2) {
    if (str1 == null || str2 == null)
        return str1 == str2;

    return str1.equals(str2);
}


0

では、「最善の解決策」とはどういう意味ですか?

最も読みやすいということであれば、すべての可能な解決策は、経験豊富なJavaプログラマーにとってほぼ同等です。しかし、IMOで最も読みやすいのはこれです。

 public boolean compareStringsOrNulls(String str1, String str2) {
     // Implement it how you like
 }

つまり、インライン化できる(理想的には)単純なメソッド内に実装を隠します。

(コードベースですでに使用している場合は、サードパーティのユーティリティライブラリに「アウトソース」することもできます。)


最もパフォーマンスが高い場合は、次のようにします。

  1. 最もパフォーマンスの高いソリューションは、プラットフォームとコンテキストに依存します。
  2. 「コンテキスト」の問題の1つは、発生の相対(動的)頻度です。 null引数。
  3. それはおそらく、違いはアプリケーション全体のパフォーマンスに違いを確認するために、おそらく小さすぎるため...速いされているバージョンは関係せず、
  4. それが重要な場合は、プラットフォームでどちらが最も速いかを判断する唯一の方法は、両方のバージョンを試して違いを測定することです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.