WeakHashSet
This commit is contained in:
parent
bb7063c7f8
commit
40459a7e99
@ -0,0 +1,25 @@
|
||||
package ru.dbotthepony.kommons.collect
|
||||
|
||||
import it.unimi.dsi.fastutil.Hash
|
||||
import java.lang.ref.Reference
|
||||
|
||||
object ReferenceHashStrategy : Hash.Strategy<Any?> {
|
||||
override fun equals(a: Any?, b: Any?): Boolean {
|
||||
if (a === b) return true
|
||||
if (a == null || b == null) return false
|
||||
|
||||
if (a is Reference<*>) {
|
||||
val ref = a.get()
|
||||
if (b is Reference<*>) return ref != null && ref == b.get()
|
||||
return ref == b
|
||||
} else if (b is Reference<*>) {
|
||||
return b.get() == a
|
||||
} else {
|
||||
return a == b
|
||||
}
|
||||
}
|
||||
|
||||
override fun hashCode(o: Any?): Int {
|
||||
return o.hashCode()
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package ru.dbotthepony.kommons.collect
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenCustomHashSet
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet
|
||||
import ru.dbotthepony.kommons.util.HashedWeakReference
|
||||
import java.lang.ref.ReferenceQueue
|
||||
|
||||
class WeakHashSet<E : Any>(initialCapacity: Int = 16, loadFactor: Float = 0.75f, linked: Boolean = false) : MutableSet<E> {
|
||||
private val queue = ReferenceQueue<E>()
|
||||
private val backing: ObjectSet<Any> = if (linked) ObjectLinkedOpenCustomHashSet(initialCapacity, loadFactor, ReferenceHashStrategy) else ObjectOpenCustomHashSet(initialCapacity, loadFactor, ReferenceHashStrategy)
|
||||
|
||||
private fun purge() {
|
||||
var next = queue.poll()
|
||||
|
||||
while (next != null) {
|
||||
backing.remove(next)
|
||||
next = queue.poll()
|
||||
}
|
||||
}
|
||||
|
||||
override fun add(element: E): Boolean {
|
||||
purge()
|
||||
if (element in backing) return false
|
||||
return backing.add(HashedWeakReference(element, queue))
|
||||
}
|
||||
|
||||
override fun addAll(elements: Collection<E>): Boolean {
|
||||
var any = false
|
||||
elements.forEach { any = add(it) || any }
|
||||
return any
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
backing.clear()
|
||||
while (queue.poll() != null) {}
|
||||
}
|
||||
|
||||
override fun iterator(): MutableIterator<E> {
|
||||
purge()
|
||||
return backing.iterator().map { (it as HashedWeakReference<E>).get() }.filterNotNull()
|
||||
}
|
||||
|
||||
override fun remove(element: E): Boolean {
|
||||
purge()
|
||||
return backing.remove(element)
|
||||
}
|
||||
|
||||
override fun removeAll(elements: Collection<E>): Boolean {
|
||||
purge()
|
||||
return backing.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<E>): Boolean {
|
||||
purge()
|
||||
return backing.retainAll(elements)
|
||||
}
|
||||
|
||||
override val size: Int get() {
|
||||
purge()
|
||||
return backing.size
|
||||
}
|
||||
|
||||
override fun contains(element: E): Boolean {
|
||||
purge()
|
||||
return backing.contains(element)
|
||||
}
|
||||
|
||||
override fun containsAll(elements: Collection<E>): Boolean {
|
||||
purge()
|
||||
return backing.containsAll(elements)
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
purge()
|
||||
return backing.isEmpty()
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package ru.dbotthepony.kommons.util
|
||||
|
||||
import java.lang.ref.ReferenceQueue
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
* [WeakReference], but with [hashCode] overridden with hash of referent object
|
||||
*/
|
||||
@Suppress("EqualsOrHashCode")
|
||||
class HashedWeakReference<T : Any> : WeakReference<T> {
|
||||
constructor(value: T) : super(value) {
|
||||
hash = value.hashCode()
|
||||
}
|
||||
|
||||
constructor(value: T, queue: ReferenceQueue<T>) : super(value, queue) {
|
||||
hash = value.hashCode()
|
||||
}
|
||||
|
||||
private val hash: Int
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return hash
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "HashedWeakReference[hash=$hash]"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user