Kai Yuan
12/23/2022, 1:13 PMdata class
and set.contains(e)
If I didn't understand it wrong, set.contains(e)
checks elementInSet.equals(e)
. Also, data class creates equals()
method for the properties in the primary constructor.
Now, I'm wondering why I get this output:
data class Foo(var v: Int)
fun test() {
val mySet = mutableSetOf(Foo(1))
mySet.forEach {
it.v += 1
}
println("mySet contains: $mySet")
val f = Foo(2)
println("$f in Set? ${f in mySet}")
println("equals? ${f == mySet.toList().first()}")
}
Output:
mySet contains: [Foo(v=2)]
Foo(v=2) in Set? false
equals? true
Why f in mySet
returns false?mkrussel
12/23/2022, 1:17 PMmutableSetOf
creates a linked hash set and it not suitable for storing mutable objects. I'm not aware of any efficient set that can handle mutable objects.
When you change v
you change the hashcode
of the Foo
object and the set can no longer find it.Kai Yuan
12/23/2022, 1:22 PMboolean contains(Object o)
Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
mkrussel
12/23/2022, 1:23 PMequals
, but it uses hashcode
to reduce the number of items to consider for equals
. So it will only use equals
when the hashcode
puts them in the same bucket.CLOVIS
12/23/2022, 1:25 PMhashCode
contract ensures that using the hash code to make fast equality checks is always legal, so it doesn't have to be documented everywhere
It's not legal in Java or Kotlin to add an object whose identity changes over time as a key (value in a set, key in a map…)Kai Yuan
12/23/2022, 1:25 PMSet.contains()
?CLOVIS
12/23/2022, 1:26 PMSet
is an interface, HashSet
and LinkedHashSet
don't behave the same way.mkrussel
12/23/2022, 1:26 PMHashSet
behaves the same way, and TreeSet
actual breaks that contract.CLOVIS
12/23/2022, 1:27 PM"returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).Does not mean that the function calls only equals. It means that, for a well implemented object, it behaves the same way as if it did.
CLOVIS
12/23/2022, 1:28 PMSet
implementations in Java and Kotlin do respect that contractKai Yuan
12/23/2022, 1:30 PMCLOVIS
12/23/2022, 1:30 PMmkrussel
12/23/2022, 1:31 PMDate
is a mutable object, but I would still store them in Sets
because I know that I would not modify them and I pretended they were immutable.mkrussel
12/23/2022, 1:32 PMSet
class documentation.
Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set. A special case of this prohibition is that it is not permissible for a set to contain itself as an element.
Kai Yuan
12/23/2022, 1:33 PMCLOVIS
12/23/2022, 1:35 PM