love.forte.simbot.utils.WeakMap.kt Maven / Gradle / Ivy
package love.forte.simbot.utils
import java.lang.ref.Reference
import java.lang.ref.ReferenceQueue
import java.lang.ref.WeakReference
/**
*
* Value值为 weak 的 Map。
*
* @author ForteScarlet
*/
public class WeakMap(private val delegateMap: MutableMap>) : MutableMap {
private val queue = ReferenceQueue()
private inner class WeakReferenceWithKey(val key: K, value: V) : WeakReference(value, queue)
init {
}
private fun checkWeak() {
var polled: Reference? = queue.poll()
while (polled != null) {
if (polled is WeakMap<*, *>.WeakReferenceWithKey<*>) {
remove(polled.key)
}
polled = queue.poll()
}
}
override val size: Int get() = delegateMap.size
override fun containsKey(key: K): Boolean = checkWeak().let { delegateMap.containsKey(key) }
override fun containsValue(value: V): Boolean = checkWeak().let {
delegateMap.values.any { it.get()?.equals(value) ?: false }
}
override fun get(key: K): V? {
checkWeak()
return delegateMap[key]?.get()
}
override fun isEmpty(): Boolean {
checkWeak()
return delegateMap.isEmpty()
}
@Suppress("UNCHECKED_CAST")
override val entries: MutableSet>
get() = checkWeak().let {
delegateMap.entries.mapNotNull {
val k = it.key
val v = it.value.get() ?: return@mapNotNull null
Entry(k, v) as MutableMap.MutableEntry
}.toMutableSet()
}
override val keys: MutableSet
get() = checkWeak().let { delegateMap.keys }
override val values: MutableCollection
get() = checkWeak().let { delegateMap.values.mapNotNull { it.get() } }.toMutableList()
override fun clear() {
delegateMap.clear()
}
override fun put(key: K, value: V): V? {
return delegateMap.put(key, WeakReferenceWithKey(key, value))?.get()
}
override fun putAll(from: Map) {
from.forEach { (k, u) -> put(k, u) }
}
override fun remove(key: K): V? {
return delegateMap.remove(key)?.get()
}
}
private class Entry(override val key: K, override var value: V) : MutableMap.MutableEntry {
override fun setValue(newValue: V): V {
val old = value
value = newValue
return old
}
}