Scalaの==と.equalsの違いは何ですか?


144

違いは何である==.equals()スカラ座では、いつどの使用するには?

実装はJavaと同じですか?

編集:関連する質問は、の特定のケースについて話しAnyValます。より一般的なケースはAnyです。



@ベン質問された日付を考慮して、他の質問は重複としてマークする必要があると思います。また、二つの質問は違うと思います。
Jus12、

回答:


201

を適切に処理することを除いて==、通常はを使用します。参照の等価性(めったに使用されない)はです。equalsnulleq


12
Javaライブラリの使用時にも適用されますか?
Jus12

20
します。たとえば、新しいjava.util.ArrayList [Int]()== new java.util.ArrayList [Int]()です。
Didier Dupont

5
また、IntとLong、および==と.equals()の間にいくつかの奇妙な動作があります。IntおよびLongと同じ数は、==の場合はtrueを返し、等しい場合はfalseを返します。したがって、==は常に等しいルートにルーティングされるわけではありません。
Harold L

24
さらに興味深いことに、両方3 == BigInt(3)BigInt(3) == 3真です。しかし、3.equals(BigInt(3))は偽ですが、BigInt(3).equals(3)真です。したがって、を使用することをお勧めし==ます。Scalaでの使用equals()は避けてください。==暗黙の変換はうまくいくと思いますが、equals()そうではありません。
Naetmul 2013

では、なぜfalseであるのにnew java.lang.Integer(1) == new java.lang.Double(1.0)true new java.lang.Integer(1) equals new java.lang.Double(1.0)であるのでしょうか。
Eastsun 2016

34

==はfinalメソッドであり、final .equalsではないを呼び出します。

これは==、メソッドではなく演算子であり、オブジェクトの参照の等価性を厳密に比較するJavaとは根本的に異なります。


29

TL; DR

  • equals各インスタンスのコンテンツを比較するオーバーライドメソッド。これは、equalsJavaで使用されるのと同じメソッドです。
  • 参照==を気にせずに演算子を使用して比較するnull
  • 使用するeq両方の引数があるかどうかを確認する方法を丁度同じ参照。これがどのように機能するかを理解していない限り使用しないことをお勧めしますequals。そしてAnyRef、これだけでなく、引数でのみ使用するようにしてくださいAny

注:の場合にはequals、あなたが例えば引数に切り替える場合は、単にJavaでのように、それは同じ結果を返さないことが1.equals(BigInt(1))返されますfalse逆に返される場所をtrue。これは、各実装が特定のタイプのみをチェックするためです。プリミティブ番号は、2番目の引数が型ではなく、他のプリミティブ型のみであるかどうかをチェックしNumberませんBigInt

細部

このAnyRef.equals(Any)メソッドは、サブクラスによってオーバーライドされるメソッドです。Scalaにも導入されたJava仕様のメソッド。ボックス化されていないインスタンスで使用すると、これを呼び出すためにボックス化されます(Scalaでは非表示ですが、Javaではint->を使用するとよりわかりやすくなりますInteger)。デフォルトの実装は単に参照を比較するだけです(Javaのように)

このAny.==(Any)メソッドは2つのオブジェクトを比較し、どちらかの引数をnullにすることができます(2つのインスタンスで静的メソッドを呼び出す場合と同様)。両方がnullであるかどうかを比較し、equals(Any)ボックス化されたインスタンスのメソッドを呼び出します。

AnyRef.eq(AnyRef)この方法は、比較のみインスタンスがメモリに配置されている参照を、。このメソッドには暗黙のボックス化はありません。

  • 1 equals 2返されfalse、それがリダイレクトとして、Integer.equals(...)
  • 1 == 2返されfalse、それがリダイレクトとして、Integer.equals(...)
  • 1 eq 2 両方の引数が型である必要があるため、コンパイルされません AnyRef
  • new ArrayList() equals new ArrayList()戻りますtrue、それは内容を確認して、
  • new ArrayList() == new ArrayList()返されtrue、それがリダイレクトとして、equals(...)
  • new ArrayList() eq new ArrayList()false両方の引数が異なるインスタンスであるため、が返されます
  • foo equals fooが返されますがtrue、でない場合foonullNullPointerException
  • foo == foo返されtrueたとしても、fooですnull
  • foo eq footrue両方の引数が同じ参照にリンクしているため、が返されます

6

==およびequalsfor FloatDoubletypeの間には興味深い違いがありNaNます。

scala> Double.NaN == Double.NaN
res3: Boolean = false

scala> Double.NaN equals Double.NaN
res4: Boolean = true

編集:コメントで指摘されたように-「これはJavaでも発生します」- これが正確に何であるかに依存します

public static void main(final String... args) {
    final double unboxedNaN = Double.NaN;
    final Double boxedNaN = Double.valueOf(Double.NaN);

    System.out.println(unboxedNaN == unboxedNaN);
    System.out.println(boxedNaN == boxedNaN);
    System.out.println(boxedNaN.equals(boxedNaN));
}

これは印刷されます

false
true
true

だから、unboxedNan利回りfalseこれはIEEE浮動小数点数がそれをどう定義するかで、(それが何らかの形でアイデンティティの概念を台無しが)これは本当にすべてのプログラミング言語で起こる必要があるため、等しいかどうかを比較。

ボックス化されたNaNは、==オブジェクト参照を比較しているため、Javaを使用した比較ではtrueになります。

私はequalsケースの説明はありませんが、私見では==ボックス化されていないdouble値と同じように動作するはずですが、実際には動作しません。

Scalaに翻訳すると、Scalaはプリミティブ型とオブジェクト型を統合しAny、必要に応じてプリミティブdoubleとボックス型Doubleに変換するため、問題はもう少し複雑になります。したがって、スカラは==明らかにプリミティブNaN値の比較に要約されますがequals、ボックス化されたDouble値で定義されたものを使用します(多くの暗黙の変換マジックが進行中で、によってdoubleにピンプされたものがありRichDoubleます)。

実際に何かがNaN使用されているかどうかを本当に確認する必要がある場合isNaN


そしてこれはJavaでも起こります!
Iwan Satria、2016年

4

Scalaでは==最初にNull値をチェックしてから、最初のオブジェクトでequalsメソッドを呼び出します

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