Equality in Kotlin

Comparing references and data in Kotlin

Jasmeet Kaur
2 min readNov 2, 2020

There are three ways to check equality in Kotlin:

1) Structural Equality(‘==’)

‘==’ in Kotlin compares the data contained in the variables. In Java, however, it is used to compare the references of the two variables.

In case of user defined classes, ‘==’ compares the contents if the class is a “data” class. Otherwise, it compares the references.

2) Referential Equality(‘===’)

‘===’ in Kotlin compares the references of the two variables. However, in case of primitives the ‘===’ check is equivalent to the ‘==’ check, i.e, it checks the values.

3) equals method

The ‘equals’ method behaves the same as the ‘==’ in Kotlin.

However, there is a difference between the ‘equals’ method and ‘==’ in case of Float and Double comparisons. ‘==’ follows the IEEE 754 standard in case of Float and Double comparisons, however, ‘equals’ does not, which means in case of equals:

  • NaN is considered equal to itself
  • NaN is considered greater than any other element including POSITIVE_INFINITY
  • 0.0 is considered less than 0.0.

Let us look at the examples below to understand further the comparisons for different cases.

1) Primitive comparisons

val firstInt = 5
val secondInt = 5

println(firstInt == secondInt) // true
println
(firstInt === secondInt) // true
println
(firstInt.equals(secondInt)) // true

For all the comparisons in case of primitive types, the data is compared in case of primitives.

2) Primitive Wrapper comparisons

val firstInt = Integer(5)
val secondInt = Integer(5)
println(firstInt == secondInt) // true
println
(firstInt === secondInt) // false
println
(firstInt.equals(secondInt)) // true

Here, firstInt and secondInt have different references. Hence, the referential equality check(‘===’) returns false.The structural and the equals check only the content. Hence return true since the data, i.e, 5 is equal.

3) User defined class object comparisons

class Student(val name : String)val student1 = Student(“Jasmeet”)
val student2 = Student(“Jasmeet”)
println(student1 === student2) // false
println(student1 == student2) // false
println(student1.equals(student2)) // false
println(student1.name === student2.name) // true
println(student1.name == student2.name) // true
println(student1.name.equals(student2.name)) // true

Here, as student is neither a primitive nor a wrapper type, all the comparison checks compare the references and not the content. However, in case of string literal comparisons, the content is compared as in Java.

For the content comparison to work, the class has to be a data class.

data class Student(val name : String)val student1 = Student(“Jasmeet”)
val student2 = Student(“Jasmeet”)
println(student1 === student2) // false
println(student1 == student2) // true
println(student1.equals(student2)) // true

4) Negative Zero and Positive Zero comparisons

val negativeZero = -0.0f
val positiveZero = 0.0f

println(negativeZero == positiveZero) // true
println
(negativeZero.equals(positiveZero)) // false

As mentioned earlier, negativeZero and positiveZero comparsion follows IEEE 754 in case of ‘==’ and hence returns true and ‘equals’ does not follow the same, hence, returns false.

--

--