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