Scala Tutorial
Basics
Control Statements
OOP Concepts
Parameterized - Type
Exceptions
Scala Annotation
Methods
String
Scala Packages
Scala Trait
Collections
Scala Options
Miscellaneous Topics
In Scala, the topic of object equality is multi-faceted due to its support for both object-oriented and functional programming paradigms. When you want to check if two objects are equal, there are a few things to consider:
Reference Equality (eq
and ne
):
Using eq
checks if two object references point to the same location in memory, i.e., they're the same instance. The opposite is ne
, which checks if they are different instances.
val a = new String("Hello") val b = new String("Hello") println(a eq b) // false
Structural Equality (==
and !=
):
The ==
method checks for structural equality. By default, this behaves the same way as Java's equals
method. However, in Scala, many collections and other classes override this to provide a more intuitive comparison.
val list1 = List(1, 2, 3) val list2 = List(1, 2, 3) println(list1 == list2) // true
For custom classes, you'll often override the equals
method (and hashCode
) to provide appropriate behavior:
class Point(val x: Int, val y: Int) { override def equals(obj: Any): Boolean = obj match { case p: Point => p.x == x && p.y == y case _ => false } override def hashCode(): Int = (x, y).hashCode() } val p1 = new Point(1, 2) val p2 = new Point(1, 2) println(p1 == p2) // true
Type-safe Equality with ===
:
While ==
is widely used, it's not type-safe. For example, 1 == "1"
compiles but will always return false
. To achieve type-safe equality, libraries like Cats or Scalaz provide ===
:
import cats.implicits._ println(1 === 1) // true // println(1 === "1") // This would not compile
Case Classes and Equality:
One of the advantages of case classes in Scala is that they automatically derive implementations of equals
and hashCode
methods based on the structure of the class:
case class Point(x: Int, y: Int) val p1 = Point(1, 2) val p2 = Point(1, 2) println(p1 == p2) // true
==
and !=
for structural equality for most use-cases in Scala.equals
(and hashCode
) for custom classes when needed.equals
and hashCode
.In any case, always be aware of the type of equality you need and ensure you're using the right method for the job.
Equality testing in Scala:
val x: Int = 42 val y: Int = 42 val areEqual: Boolean = x == y
Comparing objects in Scala:
==
) or inequality operator (!=
).val string1: String = "Hello" val string2: String = "World" val areNotEqual: Boolean = string1 != string2
Equals method in Scala:
equals
method is used to check structural equality of objects.val person1: Person = Person("John", 30) val person2: Person = Person("John", 30) val areEqual: Boolean = person1.equals(person2)
HashCode and equals contract in Scala:
hashCode
and equals
methods must be consistent to satisfy the contract. If two objects are equal, their hash codes must be equal.class Student(val id: Int, val name: String) { override def equals(obj: Any): Boolean = { obj match { case s: Student => id == s.id && name == s.name case _ => false } } override def hashCode(): Int = id.hashCode() + name.hashCode() }
Reference equality vs. structural equality in Scala:
eq
and ne
) checks if two references point to the exact same object, while structural equality checks if two objects are equivalent based on their content.val string1: String = new String("Hello") val string2: String = new String("Hello") val areReferenceEqual: Boolean = string1 eq string2 val areStructurallyEqual: Boolean = string1 == string2
Case class equality in Scala:
equals
method based on their fields.case class Point(x: Int, y: Int) val point1: Point = Point(1, 2) val point2: Point = Point(1, 2) val areEqual: Boolean = point1 == point2
Customizing equality in Scala:
equals
and hashCode
methods for user-defined classes.class Book(val title: String, val author: String) { override def equals(obj: Any): Boolean = { obj match { case b: Book => title == b.title && author == b.author case _ => false } } override def hashCode(): Int = title.hashCode() + author.hashCode() }
Equality for Option and Either types in Scala:
Option
and Either
involves checking the equality of their contents.val option1: Option[String] = Some("Scala") val option2: Option[String] = Some("Scala") val areEqual: Boolean = option1 == option2