compareTo()とequals()の比較


118

StringJavaのの等価性をテストするときは、equals()これが最も自然な方法のように思えるため、常に使用しました。結局のところ、その名前はすでに意図されていることを示しています。しかし、私の同僚は最近、のcompareTo() == 0代わりに使用するように教えられたと私に言ったequals()。これは不自然に感じられ(compareTo()順序付けを提供し、同等性を比較しないことを意味します)、多少危険compareTo() == 0でもあります(すべての場合において同等であることを意味するわけではないため、必ずしもそうであるとは限りませんString)。

彼はfor のcompareTo()代わりに使用するように教えられた理由を知りませんでした。また、理由もわかりませんでした。これは本当に個人的な好みの問題ですか、それともどちらの方法にも本当の理由がありますか?equals()String


9
厳密に言えば、マイクロ最適化レベルで話すことは、時期尚早に話すべきではありません.equalsIgnoreCase()が、適切な場合は最速の比較.equals()です。それ以外の場合は必要です。

1
これは古い質問ですが、強調したいナゲットが含まれています。「compareTo() == 0必ずしもすべてのケースで平等を意味するわけではありません」。これは完全に正しいです!これは、Java API仕様(たとえば、Comparableクラスの仕様)で「consistent with equals」が意味することとまったく同じです。たとえば、Stringの比較メソッドは、equalsと整合性がありますが、BigDecimalの比較メソッドは、equals と整合性がありません
スチュアートマーク

回答:


104

違いは、NullPointerException "foo".equals((String)null)"foo".compareTo((String)null) == 0スローするときにfalseを返すことです。したがって、文字列であっても常に互換性があるわけではありません。


6
これについても言及する必要があると思います。equalsはハッシュコードを計算します。2つの異なる文字列のハッシュコードは、まれではありますが、同じにすることができます。ただし、compareTo()を使用すると、文字列が文字ごとにチェックされます。したがって、この場合、2つの文字列は、実際の内容が等しい場合にのみtrueを返します。
アシュウィン

30
equalsがハッシュコードを計算するのはなぜだと思いますか?これはそうではないことがわかります:docjar.com/html/api/java/lang/String.java.html(1013行目)。
ワックスウィング

3
あなたが正しいです。等しいとハッシュコードは関連していると思いました(等しいは両方が同じハッシュコードを持っているかどうかをチェックします)。次に、これらのメソッドのいずれか1つをオーバーライドする場合、これらのメソッドを両方ともオーバーライドする必要があるのはなぜですか。
Ashwin

3
我々が等号をオーバーライドするときに、クラスがクラス文句を言わないが正しく機能HashMapの、HashSetの、およびハッシュテーブルなどのハッシュベースのコレクションを、使用している場合ので、ハッシュコードをオーバーライドする必要がある
varunthacker

4
@Ashwin .equalsがtrueを返す場合、ハッシュコードも等しいはずなので、これが必要です。ただし、ハッシュコードが等しい場合、.equalsがtrueを返す必要があることを意味するわけではありません
Alan

33

主な2つの違いは次のとおりです。

  1. equalsパラメータとして任意のオブジェクトを受け取りますが、compareTo文字列のみを受け取ります。
  2. equalsそれらが等しいかどうかをcompareTo通知するだけで、文字列を辞書式に比較する方法に関する情報を提供します。

私はStringクラスのコードを見て compareToとequals内のアルゴリズムは基本的に同じに見えます。私は彼の意見は単なる好みの問題であると私は思います。あなたが知る必要があるのは、文字列の平等であり、辞書順で最初に来る文字列ではない場合、私はを使用しますequals


26

等しいかどうかを比較するときequals()は、意図を明確に表すため、を使用する必要があります。

compareTo() 追加の欠点は、それを実装するオブジェクトでのみ機能することです。 Comparableインターフェースます。

これは、文字列だけでなく、一般に適用されます。


18

compareTo文字列の長さが異なる場合、より多くの作業を行う必要があります。equalsは単にfalseを返すことができcompareToますが、並べ替え順序を見つけるのに十分な文字を常に調べる必要があります。


10

compareTo()文字列だけでなくcompareTo<T>、一般的な引数を取るため、他のオブジェクトにも適用されますT。文字列はcompareTo()Comparableインターフェイスを実装することによってメソッドを実装したクラスの1つです。(compareTo()は、対応するインターフェースのメソッドです)。したがって、どのクラスでもComparableインターフェースを自由に実装できます。

ただしcompareTo()、オブジェクトの順序を指定します。通常、昇順または降順でオブジェクトをソートするときに使用されますがequals()、等値についてのみ説明し、それらが等しいかどうかを示します。


10

文字列コンテキスト:
compareTo:2つの文字列を辞書式に比較します。
等しい:この文字列を指定されたオブジェクトと比較します。

compareToは、2つの文字列を(同じインデックスの)文字で比較し、それに応じて整数(正または負)を返します。

String s1 = "ab";
String s2 = "ab";
String s3 = "qb";
s1.compareTo(s2); // is 0
s1.compareTo(s3); // is -16
s3.compareTo(s1); // is 16

7

equals()は、compareTo()よりも効率的です。

compareToとequalsの非常に重要な違い:

"myString".compareTo(null);  //Throws java.lang.NullPointerException
"myString".equals(null);     //Returns false

equals()は、2つのオブジェクトが同じかどうかをチェックし、ブール値を返します。

compareTo()(インタフェースComparableから)は整数を返します。2つのオブジェクトのどちらが「より小さい」、「等しい」、または「より大きい」かをチェックします。すべてのオブジェクトを論理的に順序付けできるわけではないため、compareTo()メソッドが常に意味をなすわけではありません。

equals()は、compareTo()のようにオブジェクト間の順序を定義しないことに注意してください。

ここで、両方のメソッドのソースコードを確認して、いくつかの数学計算を伴うcompareToよりもequalsの方が望ましいと結論付けます。


5

どちらのメソッドもほとんど同じことをしているように見えますが、compareTo()メソッドはObjectではなくStringを取り込んで、通常のequals()メソッドにいくつかの機能を追加しています。関心があるのが等価である場合は、equals()メソッドが最良の選択です。これは、コードを調べる次のプログラマにとって意味があるからです。2つの異なる関数の時間差は、大量のアイテムをループしない限り問題になりません。compareTo()は、コレクション内の文字列の順序を知る必要がある場合、または同じ文字シーケンスで始まる文字列の長さの違いを知る必要がある場合に非常に役立ちます。

ソース:http : //java.sun.com/javase/6/docs/api/java/lang/String.html


5

equals() OPの場合は、選択する方法でなければなりません。

実装を見てみるequals()と、compareTo()grepcode上java.lang.Stringで、我々は簡単に私達がちょうど2つの文字列が等しいかどうかに関係している場合は等号が優れていることがわかります。

equals()

1012   public  boolean equals(Object anObject){ 
1013 ifthis == anObject){
1014 return true ;
1015 }
1016 if(anObject instanceof String){
1017 String anotherString =(String)anObject;
1018 int n =カウント。
1019 if(n == anotherString.count){
1020 char v1 [] = value;
1021 char v2 [] = anotherString.value;
1022 inti =オフセット;
1023 int j = anotherString.offset;
1024 while(n--!= 0){
1025 if falseを返します1032 }(v1 [i ++]!= v2 [j ++])
1026 return false ;
1027 }
1028は trueを返し ます
1029 }
1030 }
1031

compareTo()

1174   public  int compareTo(String anotherString){ 
1175 int len1 = count;
1176 int len2 = anotherString.count;
1177 int n = Math。min(len1、len2); if(c1!= c2){
1178 文字 v1 [] =値。
1179 char v2 [] = anotherString.value;
1180 int i =オフセット;
1181 int j = anotherString.offset;
1183 if(i == j){
1184 int k = i;
1185 int lim = n + i;
1186 while(k <lim){
1187 文字1200 } 1201 } 1202 } c1 = v1 [k];
1188 文字 c2 = v2 [k];
1189
1190 return c1-c2;
1191 }
1192 k ++;
1193 }
1194 } else {
1195 while(n--!= 0){
1196 char c1 = v1 [i ++];
1197 文字 c2 = v2 [j ++];
1198 if(c1!= c2){
1199 return c1-c2;



1203 len1-len2を返します。
1204 }

文字列の1つが別の文字列のプレフィックスであるcompareTo()場合は、辞書式順序を決定する必要があるため、パフォーマンスは低下しますequals()が、心配する必要はなく、すぐにfalseを返します。

私の考えでは、意図したとおりにこれら2つを使用する必要があります。

  • equals() 等しいかどうかを確認する
  • compareTo() 語彙の順序を見つけるため。

3

equals()は、2つの文字列が等しいかどうかをチェックします。ブール値を提供します。compareTo()は、文字列オブジェクトが他の文字列オブジェクトと等しいか、大きいか、小さいかをチェックします。結果は次のようになります。

eq:

String a = "Amit";
String b = "Sumit";
String c = new String("Amit");
System.out.println(a.equals(c));//true
System.out.println(a.compareTo(c)); //0
System.out.println(a.compareTo(b)); //1


2

これはネクロマンシーの実験です:-)

ほとんどの回答は、パフォーマンスとAPIの違いを比較しています。2つの操作は単にセマンティクスが異なるだけであるという基本的な点を見落とします。

あなたの直感は正しいです。x.equals(y)は、x.compareTo(y)== 0と互換性がありません。最初の比較はIDを比較し、もう1つは「サイズ」の概念を比較します。多くの場合、特にプリミティブ型の場合、これら2つが一致することは事実です。

一般的なケースはこれです:

xとyが同一の場合、それらは同じ「サイズ」を共有します。x.equals(y)がtrueの場合=> x.compareTo(y)は0です。

ただし、xとyが同じサイズを共有する場合、それらが同じであることを意味するわけではありません。

x.compareTo(y)が0の場合、必ずしもx.equals(y)がtrueであるとは限りません。

IDがサイズと異なる説得力のある例は、複雑な数です。比較は絶対値で行われると仮定します。したがって、2つの複素数が与えられた場合:Z1 = a1 + b1 * iおよびZ2 = a2 + b2 * i:

Z1.equals(z2)は、a1 = a2およびb1 = b2の場合にのみtrueを返します。

ただし、Z1.compareTo(Z2)は、a1 ^ 2 + b1 ^ 2 == a2 ^ 2 + b2 ^ 2の条件を満たす限り、(a1、b1)と(a2、b2)のペアの数が無限である場合に0を返します。


1
x.equals(y)はアイデンティティを意味するのではなく、平等を意味します。IDは、Javaのユーザー定義型のx == yを使用して比較されます。
Fernando Pelliccioni 2014年

2

Equalsは、compareToよりも効率的です。

文字列内の文字シーケンスの長さが一致しない場合、文字列が等しいため、拒否がはるかに速くなる可能性があります。

さらに、それが同じオブジェクト(論理的等価ではなく同一性等価)である場合も、より効率的です。

彼らがhashCodeキャッシングも実装した場合、hashCodeが一致しない場合に不等号を拒否するほうがさらに速くなる可能性があります。


2

String.equals()instanceofオペレーターを呼び出すcompareTo()必要がありますが、必要ありません。同僚はinstanceofequals()メソッド内の呼び出しの数が多すぎるためにパフォーマンスが大幅に低下することを指摘しましたが、テストの方がcompareTo()わずかに高速であることが証明されています。

ただし、Java 1.6を使用していました。他のバージョン(または他のJDKベンダー)では、差が大きくなる可能性があります。

このテストでは、1000個の要素配列の各文字列を10回繰り返し比較しました。


1
私はあなたが非常に短い文字列を使用したに違いないと思いますが、すべて同じ長さで、最初の文字に多様性がcompareTo()あり、より速い結果を得るにはequals()?しかし、実際のデータのほとんどのセットでequals()は、よりもはるかに高速ですcompareTo() == 0equals()文字列に共通の接頭辞があり、長さが異なる場合、または文字列が実際に同じオブジェクトである場合に輝きます。
x4u

さて、私のテストは、instanceofがパフォーマンスキラーであるという仮説に対するものでした。そのため、文字列は確かに短いものでした。
ダヌビアセーラー

文字列がランダムで長さがほとんど異なる場合は、compareTo()よりもequals()メソッドを選択する方がわかりやすいでしょう。ほとんどの場合、長さが等しくない場合はすぐにfalseが返されます。
sactiw 2014年

1
  1. equalsパラメータとして任意のオブジェクトを使用compareToできますが、文字列のみを使用できます。

  2. cometo nullの場合compareTo、例外をスローします

  3. どこで差​​分が発生するか知りたい場合は、を使用できますcompareTo


compareToは、任意のオブジェクトを引数として取ることができます。@apurva jadhavが上で述べたように、compariは一般的な議論をします。comaparableをComparable <String>として実装すると、文字列のみを使用できます。
Gaurav Kumar

1
  • equals:等価性のチェックと重複の制限に必要です。Java Libraryの多くのクラスは、重複を検出したい場合に備えてこれを使用します。たとえばHashSet.add(ob1)、それが存在しない場合にのみ追加されます。したがって、このようないくつかのクラスを拡張する場合は、オーバーライドしますequals()

  • compareTo:要素の注文に必要です。繰り返しになりますが、安定した並べ替えには等号が必要なので、0が返されます。


0

等しい-

1- GetHashCodeメソッドをオーバーライドして、ハッシュテーブルで型が正しく機能するようにします。

2- Equalsメソッドの実装で例外をスローしないでください。代わりに、null引数に対してfalseを返します。

3-

  x.Equals(x) returns true.

  x.Equals(y) returns the same value as y.Equals(x).

  (x.Equals(y) && y.Equals(z)) returns true if and only if x.Equals(z) returns true.

x.Equals(y)を連続して呼び出すと、xとyによって参照されるオブジェクトが変更されない限り、同じ値が返されます。

x.Equals(null) returns false.

4-一部の種類のオブジェクトでは、参照の等価性ではなく、値の等価性についてEqualsテストを実行することが望ましいです。Equalsのそのような実装は、2つのオブジェクトが同じインスタンスでなくても、2つのオブジェクトの値が同じである場合にtrueを返します。

例えば ​​-

   Object obj1 = new Object();
   Object obj2 = new Object();
   Console.WriteLine(obj1.Equals(obj2));
   obj1 = obj2; 
   Console.WriteLine(obj1.Equals(obj2)); 

出力:-

False
True

一方、compareTo-

現在のインスタンスを同じタイプの別のオブジェクトと比較し、現在のインスタンスが他のオブジェクトと同じ順序で並べ替え順で先行、後続、または発生するかどうかを示す整数を返します。

戻る-

ゼロ未満-このインスタンスは、ソート順でobjの前にあります。ゼロ-このインスタンスは、objと同じ順序でソートされます。ゼロより大きい-このインスタンスは、ソート順でobjに従います。

オブジェクトがインスタンスと同じタイプでない場合は、ArgumentExceptionをスローできます。

たとえば、ここにアクセスできます。

したがって、compareToの代わりにEqualsを使用することをお勧めします。


GetHashCode()方法はありません。もしかしてhashCode()
ローン侯爵

0

「等しい」はオブジェクトを比較してtrueまたはfalseを返し、「compare to」はtrueの場合は0を返します。falseの場合は[> 0]または[<0]の場合の例を次に示します。

<!-- language: lang-java -->
//Objects Integer
Integer num1 = 1;
Integer num2 = 1;
//equal
System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));
//New Value
num2 = 3;//set value
//diferent
System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));

結果:

num1.equals(num2) =true
num1.compareTo(num2) =0
num1.equals(num2) =false
num1.compareTo(num2) =-1

ドキュメント比較対象:https : //docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html

等しいドキュメント:https ://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object


0

使用している間ここに一つのことは重要であるcompareTo()以上equals()というcompareTo道具「同等」インターフェイスそのクラスのための作品は、それ以外の場合はスローされますNullPointerExceptionStringクラスはComparableインターフェイスを実装しますが、オブジェクトでStringBufferは使用できませんが"foo".compareTo("doo")Stringオブジェクトでは使用できませんStringBuffer


0
String s1 = "a";
String s2 = "c";

System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

これは-2とfalseを出力します

String s1 = "c";
String s2 = "a";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

これは2とfalseを出力します

String s1 = "c";
String s2 = "c";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));

これは0とtrueを出力します

equalsは、両方の文字列が一致する場合にのみブール値を返します。

compareToは、それらが一致するかどうかを伝えるだけでなく、どのStringが他よりも小さいか、また辞書式でどの程度かを伝えることも意図しています。これは主にコレクションでのソート中に使用されます。


-1

私は信じているequalsequalsIgnoreCaseのメソッドStringの戻りtruefalseは、文字列オブジェクトの値を比較したい場合に便利です、しかし、実装の場合compareTocompareToIgnoreCase正、負およびソートの場合に有用であろうゼロ値をメソッドに戻ります。

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