Lukasz Kalnik
05/16/2023, 8:48 PMdata class Directory(val directories: MutableList<Directory>, ...)
works but if I use MutableSet
instead then it crashes with a stack overflow (although the filesystem tree in the input is quite shallow, 10 hierarchy levels tops).Lukasz Kalnik
05/16/2023, 8:49 PMLukasz Kalnik
05/16/2023, 8:50 PMAbstractSet.hashCode()
also recursively calls hashCode()
of each of the set's elements.ephemient
05/16/2023, 9:43 PMephemient
05/16/2023, 9:46 PMNote: 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 affectscomparisons while the object is an element in the set.equals
Kotlin collections are just Java collections so all the same contracts apply
Lukasz Kalnik
05/16/2023, 10:05 PMLukasz Kalnik
05/16/2023, 10:06 PMdata class Directory(val parent: Directory?, val directories: MutableSet<Directory>, ...)
Lukasz Kalnik
05/16/2023, 10:07 PMhashCode()
tried to calculated the hashcode of the parent, which again called the child hashCode()
and recursion became endlessephemient
05/16/2023, 10:07 PMLukasz Kalnik
05/16/2023, 10:07 PMephemient
05/16/2023, 10:08 PMLukasz Kalnik
05/16/2023, 10:11 PMLukasz Kalnik
05/16/2023, 10:11 PMephemient
05/16/2023, 10:11 PMclass HashSet<T> {
private val contents = arrayOfNulls<T>(size / loadFactor)
fun contains(element: T): Boolean =
contents[element.hashCode().mod(contents.size)] == element
}
Lukasz Kalnik
05/16/2023, 10:11 PMephemient
05/16/2023, 10:12 PMephemient
05/16/2023, 10:12 PMephemient
05/16/2023, 10:12 PMephemient
05/16/2023, 10:12 PMPaul Woitaschek
05/16/2023, 10:14 PMLukasz Kalnik
05/16/2023, 10:16 PMLukasz Kalnik
05/16/2023, 10:20 PMadd()
and remove()
methods. So I'm not sure I understand your remark about dangers of sets being mutable.ephemient
05/16/2023, 10:21 PMLukasz Kalnik
05/16/2023, 10:21 PMLukasz Kalnik
05/16/2023, 10:21 PMLukasz Kalnik
05/16/2023, 10:21 PMLukasz Kalnik
05/16/2023, 10:22 PMLukasz Kalnik
05/16/2023, 10:22 PMephemient
05/16/2023, 10:22 PMephemient
05/16/2023, 10:22 PMLukasz Kalnik
05/16/2023, 10:23 PMephemient
05/16/2023, 10:24 PMephemient
05/16/2023, 10:25 PMephemient
05/16/2023, 10:25 PMLukasz Kalnik
05/16/2023, 10:26 PMephemient
05/16/2023, 10:26 PMLukasz Kalnik
05/16/2023, 10:29 PMLukasz Kalnik
05/17/2023, 5:49 PMPerson
containing a mutable variable name
, where equals()
and hashCode()
are based on the name
- pretty much a data class Person(var name: String)
.
Now create
val person1 = Person("Alice")
val person2 = Person("John")
and add them to a MutableSet
.
If you now ask the set about its size, it will obviously print 2
.
Now rename person2
from "John" to "Alice", so that they become equal in the sense of the equals()
method. Obviously a set should not contain two equal objects.
Yet if you ask the set about its size now, it will still print 2
. When you ask the set to print all elements' names, it will print Alice Alice
.
I suppose that's because both elements are already stored in different hash buckets in the set, because their hashes were calculated at the moment of adding them to the set - and are not being recalculated when the objects are modified.Lukasz Kalnik
05/17/2023, 5:50 PM