Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between == and .equals in Scala?

People also ask

Is == and .Equals the same?

In simple words, == checks if both objects point to the same memory location whereas . equals() evaluates to the comparison of values in the objects. If a class does not override the equals method, then by default, it uses the equals(Object o) method of the closest parent class that has overridden this method.

What is the difference between == and .Equals method when to use which?

== checks if both references points to same location or not. equals() method should be used for content comparison. equals() method evaluates the content to check the equality.

What is == in Scala?

if x equals y is true if both x and y have the same value. They do not need to refer to the identical instance. Hence, the equals method in Java and equals method in Scala behaves same. The == and !=

What is difference between == Equals () and compareTo () method?

The equals() tells the equality of two strings whereas the compareTo() method tell how strings are compared lexicographically.


You normally use ==, it routes to equals, except that it treats nulls properly. Reference equality (rarely used) is eq.


== is a final method, and calls .equals, which is not final.

This is radically different than Java, where == is an operator rather than a method and strictly compares reference equality for objects.


TL;DR

  • Override equals method to compare content of each instance. This is the same equals method used in Java
  • Use == operator to compare, without worrying about null references
  • Use eq method to check if both arguments are EXACTLY the same reference. Recommended not to use unless you understand how this works and often equals will work for what you need instead. And make sure to only use this with AnyRef arguments, not just Any

NOTE: On the case of equals, just as in Java, it may not return the same result if you switch the arguments eg 1.equals(BigInt(1)) will return false where the inverse will return true. This is because of each implementation checking only specific types. Primitive numbers dont check if the second argument is of Number nor BigInt types but only of other primitive types

Details

The AnyRef.equals(Any) method is the one overridden by subclasses. A method from the Java Specification that has come over to Scala too. If used on an unboxed instance, it is boxed to call this (though hidden in Scala; more obvious in Java with int->Integer). The default implementation merely compares references (as in Java)

The Any.==(Any) method compares two objects and allows either argument to be null (as if calling a static method with two instances). It compares if both are null, then it calls the equals(Any) method on boxed instance.

The AnyRef.eq(AnyRef) method compares only references, that is where the instance is located in memory. There is no implicit boxing for this method.

Examples

  • 1 equals 2 will return false, as it redirects to Integer.equals(...)
  • 1 == 2 will return false, as it redirects to Integer.equals(...)
  • 1 eq 2 will not compile, as it requires both arguments to be of type AnyRef
  • new ArrayList() equals new ArrayList() will return true, as it checks the content
  • new ArrayList() == new ArrayList() will return true, as it redirects to equals(...)
  • new ArrayList() eq new ArrayList() will return false, as both arguments are different instances
  • foo equals foo will return true, unless foo is null, then will throw a NullPointerException
  • foo == foo will return true, even if foo is null
  • foo eq foo will return true, since both arguments link to the same reference

There is an interesting difference between == and equals for Float and Double types: They treat NaN differently:

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

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

Edit: As was pointed out in a comment - "this also happens in Java" - depends on what exactly this is:

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));
}

This will print

false
true
true

So, the unboxedNan yields false when compared for equality because this is how IEEE floating point numbers define it and this should really happen in every programming language (although it somehow messes with the notion of identity).

The boxed NaN yields true for the comparison using == in Java as we are comparing object references.

I do not have an explanation for the equals case, IMHO it really should behave the same as == on unboxed double values, but it does not.

Translated to Scala the matter is a little more complicated as Scala has unified primitive and object types into Any and translates into the primitive double and the boxed Double as needed. Thus the scala == apparently boils down to a comparison of primitive NaN values but equals uses the one defined on boxed Double values (there is a lot of implicit conversion magic going on and there is stuff pimped onto doubles by RichDouble).

If you really need to find out if something is actually NaN use isNaN:

  • Java: https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#isNaN(double)
  • Scala: http://www.scala-lang.org/files/archive/api/2.11.8/index.html#scala.Double@isNaN():Boolean

In Scala == first check for Null values and then calls equals method on first object