String#equalsメソッドとString#contentEqualsメソッドの違い


回答:


171

String#equals()他のオブジェクトものインスタンスである場合は、文字列の内容が、また、小切手を比較していないだけStringString#contentEquals()コンテンツのみを(文字列)を比較してんではない他のオブジェクトものインスタンスであるかどうかを確認String。それは長い、それはの実装である限り何もすることができCharSequenceAOを覆うStringStringBuilderStringBufferCharBufferなど、


12
それで、それはJavaScript の演算子==(contentEquals)と===(equals)のようですか?
anestv 2013

2
@anestv Javaでは、==演算子は2つのオブジェクトの内容ではなく参照の比較のみを許可します。
ステファン、

2
@Alexは明確に言うと、Javaの==演算子は、2つのオブジェクトがメモリ内の同じ場所を指しているかどうか、または2つのプリミティブ型(byte、short、int、long、float、double、char、boolean)が等しいかどうかを確認するためのものです。
La-comadreja 2013

2
@Stephan、==言及されているのはJavaScriptのみです。Javaについては言及されていません。
Olathe 2016年

@anestv、違いがあります(たとえば、==JavaScriptはに比べてはるかに緩やかでcontentEquals、数値に影響を与えません)がequals、完全に一致するStrings型があるかどうかをチェックすることは正しいです(他のクラスは、equalsメソッドの型が緩い場合があります)。 。
Olathe 2016年

43

簡単に言うと、は実装より自由になるためString.contentEquals()、の賢い兄弟です。String.equals()String.equals()

別のString.contentEquals()方法がある理由はいくつかあります。私が考える最も重要な理由は:

  • このequals方法は再帰的でなければなりません。つまり:x.equals(y) == y.equals(x)。これaString.equals(aStringBuffer)は、と同じでなければならないことを意味しaStringBuffer.equals(aString)ます。これには、Java API開発者equals()がStringBuffer、StringBuilder、およびCharSequenceのメソッドでStringの特別な実装を行う必要があります。これは混乱するでしょう。

これはどこでString.contentEqualsでてくる。これは、スタンドアロン方式ではないしなければならない厳格な要件や規則に従うためにObject.equals。このようにして、「同等のコンテンツ」の感覚をより自由に実装できます。これにより、たとえば、StringBufferとStringをインテリジェントに比較できます。

そして、正確な違いは何ですか?

  • String.contentEquals()a String、a StringBuilder、a StringBuffer、a、CharSequenceおよびこれらのすべての派生クラスの内容を比較できます。パラメータがString型の場合、String.equals()実行されます。

  • String.equals()Stringオブジェクトのみを比較します。他のすべてのオブジェクトタイプは等しくないと見なされます。

  • String.contentEquals()比較することができStringBufferかつStringBuilderインテリジェントな方法インチ コンテンツ全体を新しいStringオブジェクトにコピーする重いメソッドを呼び出しませtoString()。代わりに、基になるchar[]配列と比較します。


31

この回答はすでにdbwによって投稿されましたが、彼はそれを削除しましたが、実行時間の比較、例外のスロー、

ソースコードString#equalsString#contentEqualsを見ると、String#contentEqualstake StringBuilderとotherの2つのオーバーライドされたメソッドがあることがわかりCharSequenceます。
それらの違いは、

  1. String#contentEquals指定された引数がある場合はNPEをスローしますがnullString#equals戻りますfalse
  2. String#equals指定された引数がinstance of Stringそれ以外の場合に返される場合にのみコンテンツを比較しますfalseが、一方で、String#contentEqualsインターフェイスを実装するすべてのオブジェクトのコンテンツをチェックしますCharSequence
  3. 以下に示すように渡された引数のメソッドをString#contentEqualsオーバーライドequalsすることにより、誤った結果または必要な結果を返すようにコードを微調整することもできますが、でこれらの微調整を行うことはできませんString#equals
    以下のコードtrueは、3文字の長さのコードがs含まれている限り、常に生成されますstring

        String s= new String("abc");// "abc";
        System.out.println(s.contentEquals(new CharSequence() 
        {
    
            @Override
            public CharSequence subSequence(int arg0, int arg1) {
                // TODO Auto-generated method stub
                return null;
            }
    
            @Override
            public int length() {
                // TODO Auto-generated method stub
                return 0;
            }
    
            @Override
            public char charAt(int arg0) {
                // TODO Auto-generated method stub
                return 0;
            }
    
    
            @Override
            public boolean equals(Object obj) 
            {
               return true;
            }
        }));
  4. String#contentEqualsString#Equals引数が指定されていinstance of Stringて、両方の長さStringが同じでも内容が等しくない場合よりも遅くなります。
    文字列がある場合String s = "madam"String argPassed = "madan"、その後s.contentEquals(argPassed)に比べて、この場合にはほぼ倍増実行時間がかかりますs.equals(argPassed)

  5. コンテンツの長さが両方の文字列で同じでない場合、関数String#contentEqualsString#Equals、ほとんどすべての場合よりもパフォーマンスが向上します。

彼の答えに追加するもう1つのポイント

  1. String#contentEqualsStringオブジェクトも比較するStringBuilder内容としながら、適切な結果を提供するString#Equals意志のリターンfalse

4
@dbwこの回答はあなたが投稿した回答からです
Prateek

@dbwその上、なぜあなたはとにかくあなたの投稿を削除したのですか?
MC Emperor

14
  • Stringクラスequals(Object o)メソッドはString比較のみを行います。しかし、contentEquals(CharSequence cs)クラスのためのチェックが拡張AbstractStringBuilderすなわち StringBufferStringBuilderおよびStringクラスも(彼らはすべてのタイプですCharSequence)。

    String str = "stackoverflow";
    StringBuilder builder = new StringBuilder(str);
    System.out.println(str.equals(builder));
    System.out.println(str.contentEquals(builder));

出力:

false
true

第STMTの出力があるfalseので、builder型ではないStringので、equals()リターンfalseが、contentEquals()のようなすべてのタイプのコンテンツをチェックしStringBuilderStringBufferStringおよびコンテンツは、従って同じであるようにtrue

  • contentEqualsスローされますNullPointerException指定された引数がある場合nullが、equals()falseを返しますので、等号()のinstanceofをチェック(if (anObject instance of String)引数がある場合はfalseを返します)null

14

contentEquals(CharSequence cs)

  • あなたがインターフェイスのいずれかの実装のインスタンスを指定した文字列値の等価性をチェックすることができますjava.lang.CharacterSequence(例えば、CharBufferSegmentStringStringBufferStringBuilder

equals(Object anObject)

  • 特定の文字列値がタイプのインスタンスのみと等しいかどうかを確認できますjava.lang.String

RTFC :)

ソースを読むことがそれを理解する最良の方法なので、両方の方法の実装を共有しています(jdk 1.7.0_45以降)。

public boolean contentEquals(CharSequence cs) {
    if (value.length != cs.length())
        return false;
    // Argument is a StringBuffer, StringBuilder
    if (cs instanceof AbstractStringBuilder) {
        char v1[] = value;
        char v2[] = ((AbstractStringBuilder) cs).getValue();
        int i = 0;
        int n = value.length;
        while (n-- != 0) {
            if (v1[i] != v2[i])
                return false;
            i++;
        }
        return true;
    }
    // Argument is a String
    if (cs.equals(this))
        return true;
    // Argument is a generic CharSequence
    char v1[] = value;
    int i = 0;
    int n = value.length;
    while (n-- != 0) {
        if (v1[i] != cs.charAt(i))
            return false;
        i++;
    }
    return true;
}

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                        return false;
                i++;
            }
            return true;
        }
    }
    return false;
 }

String#contentEquals()には別のメソッドがあります:

public boolean contentEquals(StringBuffer sb) {
    synchronized(sb) {
        return contentEquals((CharSequence)sb);
    }
}

9

equals()そして、contentEquals()で2つの方法ですString2比較するためのクラスstringsstringではStringBuffer

パラメータがcontentEquals()あるStringBufferString(charSequence)equals()2を比較するために使用されたstringscontentEquals()の内容を比較するために使用されるStringStringBuffer

メソッドcontentEqualsequals

public boolean contentEquals(java.lang.StringBuffer);
public boolean contentEquals(java.lang.CharSequence);
public boolean equals(Object o)

これは両方の方法を説明するコードです

public class compareString {
    public static void main(String[] args) {
        String str1 = "hello";    
        String str2 = "hello";

        StringBuffer sb1 = new StringBuffer("hello");
        StringBuffer sb2 = new StringBuffer("world");

        boolean result1 = str1.equals(str2);        // works nice and returns true
        System.out.println(" str1.equals(str2) - "+ result1);

        boolean result2 = str1.equals(sb1);         // works nice and returns false
        System.out.println(" str1.equals(sb1) - "+ result2);

        boolean result3 = str1.contentEquals(sb1);  // works nice and returns true
        System.out.println(" str1.contentEquals(sb1) - "+ result3);

        boolean result4 = str1.contentEquals(sb2);  // works nice and returns false
        System.out.println(" str1.contentEquals(sb2) - "+ result4);

        boolean result5 = str1.contentEquals(str2);  // works nice and returns true
        System.out.println(" str1.contentEquals(str2) - "+ result5);
    }
}

出力:

 str1.equals(str2) - true
 str1.equals(sb1) - false
 str1.contentEquals(sb1) - true
 str1.contentEquals(sb2) - false
 str1.contentEquals(str2) - true

7

String#equalsはObjectを引数として取り、それがStringオブジェクトのインスタンスかどうかをチェックします。引数オブジェクトが文字列オブジェクトの場合、コンテンツを文字ごとに比較します。両方の文字列オブジェクトの内容が同じ場合はtrueを返します。

String#contentEqualsは、引数としてCharSequenceインターフェースを取ります。CharSequenceは、i)Stringクラスまたは(ii)AbstractStringBuilder(StringBufferの親クラス、StringBuilder)の2つの方法で実装できます。

contentEquals() の長さは、任意のオブジェクトのインスタンスのチェックの前に比較されます。長さが同じ場合、引数オブジェクトがAbstractStringBuilderのインスタンスかどうかをチェックします。そうである場合(つまり、StringBufferまたはStringBuilder)、コンテンツは文字ごとにチェックされます。引数がStringオブジェクトのインスタンスの場合、String#equalsはString#contentEqualsから呼び出されます。

要するに、

引数がStringオブジェクトの場合も、String#equalsはコンテンツを文字ごとに比較します。そして、String#contentEqualsは、引数オブジェクトがCharSequenceインターフェースを実装する場合のコンテンツを比較します。

String#contentEqualsが内部的にStringオブジェクトのString#equalsを呼び出すので、2つの同じ長さの文字列コンテンツを比較する場合、String#contentEqualsは遅くなります。

コンテンツの長さが異なるオブジェクト(たとえば、「abc」と「abcd」)を比較しようとする場合、String#contentEqualsはString#equalsより高速です。オブジェクトインスタンスのチェック前に長さが比較されるためです。


6

contentEquals()方法チェックは内容が間で同一であるStringStringBufferなど、その文字列のいくつかの種類。


5

ところで、違いの歴史的な理由は、Stringには元々スーパークラスがなかったため、String.equals()はStringを引数として取るということです。CharSequenceがStringのスーパークラスとして導入されたとき、すべてのCharSequence実装全体で機能する独自の等価テストが必要でした。これは、Stringですでに使用されているequals()と衝突しないため、CharSequence.contentEquals( )、Stringによって継承されます。

CharSequenceがJava 1.0に存在する場合、ProbalbyにはCharSequence.equals()のみがあり、Stringはそれを実装するだけです。

ああ、進化する言語の喜び...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.