In Kotlin, I have a MutableSet
of a data class. The data class does not override equals()
or hashCode()
. I've been encountering bugs involving duplicate objects in the set, and I noticed that calling foo.containsAll(foo)
returns false
for the set.
I went through each item in the set and only a handful return false
for foo.contains(foo.toList()[i])
. For those that do, calling foo.toList()[i] == foo.toList()[i]
returns true
. So, equality checking works.
What is going on here?
I believe the only way this is possible (short of reflection, etc.) is if your data class contains something mutable and an instance changing state after being added to the set, etc. e.g.
data class Foo(var int: Int = 0)
data class Bar(val string: String, val foo: Foo = Foo())
val bars = mutableSetOf<Bar>()
bars += Bar("")
bars += Bar("")
println(bars.containsAll(bars)) // true
bars.first().foo.int = 12
println(bars.containsAll(bars)) // false
This is because the result of hashCode()
is being used in the set to identify it but if the state changes in an instance of your data class then it will likely have a different hash value causing issues like this.
In general elements in sets and keys in maps should be immutable to avoid this issue.