
commonMain.WeakMap.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weak-jvm Show documentation
Show all versions of weak-jvm Show documentation
Weak references and maps for Kotlin Multiplatform
package opensavvy.pedestal.weak
import kotlin.reflect.KProperty
/**
* A weak map is a map in which elements can be garbage-collected at any moment.
*
* The exact timing in which elements can be garbage-collected is implementation-defined.
* Some implementations may allow garbage-collection of keys, some may allow garbage-collection of values,
* or some entirely different behavior.
*
* This class expresses that an association between two values exists, but we may be capable of regenerating it
* if it disappears, or we simply don't have an important enough need for it to keep memory.
*
* Unlike regular [Map], this interface doesn't allow iteration.
* It is not possible to observe the contents of this map, since they are ever mutable
* and elements may disappear at any time.
* Some implementations may provide such observability features.
*
* ### Obtain instances
*
* The default implementation is available via the top-level [WeakMap] function.
* Other implementations are available in the `algorithms` subpackage.
*/
interface WeakMap {
/**
* Gets the value associated with [key] in this map.
*
* If no value is currently associated with [key], `null` is returned.
*
* @see Map.get Equivalent method for regular maps.
*/
operator fun get(key: K): V?
/**
* Associates [value] to the [key].
*
* An implementation may remove this association at any time.
*
* @see MutableMap.set Equivalent method for regular maps.
*/
operator fun set(key: K, value: V)
/**
* Checks whether a value is currently associated with [key].
*
* **Note.** Values may be removed at any-time.
* It is possible that a [get] call returns `null`,
* even if it is directly following a [contains] call that returned `true`.
*
* @see Map.contains Equivalent method for regular maps.
*/
@ExperimentalWeakApi
operator fun contains(key: K): Boolean
/**
* Removes [key] from this map and returns the previously-stored value.
*
* If no value was previously stored, `null` is returned (same behavior as [get], but in a single operation).
*
* @see MutableMap.remove Equivalent method for regular maps.
*/
@ExperimentalWeakApi
fun remove(key: K): V?
companion object
}
// region Constructors
/**
* Instantiates a new, empty [WeakMap].
*
* The map returned by this function has weak keys: keys of the map
* may be freed if they are not referred to elsewhere in the program.
* When a key is freed, its value is freed as well.
*
* Values are strongly held: until a key is removed from the map,
* it may never be freed by the garbage-collector.
*
* The way the map decides whether two keys are identical is implementation-defined.
* For example, some implementations may use referential equality, some others may
* use the [Any.equals] function.
*/
@ExperimentalWeakApi
expect fun WeakMap(): WeakMap
/**
* Instantiates a new [WeakMap] by copying [values].
*
* The map returned by this function has weak keys: keys of the map
* may be freed if they are not referred to elsewhere in the program.
* When a key is freed, its value is freed as well.
*
* Values are strongly held: until a key is removed from the map,
* it may never be freed by the garbage-collector.
*
* The way the map decides whether two keys are identical is implementation-defined.
* For example, some implementations may use referential equality, some others may
* use the [Any.equals] function.
*/
@ExperimentalWeakApi
expect fun WeakMap(values: Map): WeakMap
// endregion
// region getOrXXX helpers
/**
* Attempts to find the value associated with [key], returning [defaultValue] if none is found.
*/
@ExperimentalWeakApi
inline fun WeakMap.getOrDefault(key: K, defaultValue: V): V =
get(key) ?: defaultValue
/**
* Attempts to find the value associated with [key], returning the result of [defaultValue] if none is found.
*
* @see Map.getOrElse Equivalent method for regular maps.
*/
@ExperimentalWeakApi
inline fun WeakMap.getOrElse(key: K, defaultValue: () -> V): V =
get(key) ?: defaultValue()
/**
* Attempts to find the value associated with [key].
*
* If no value is associated with [key], calls [defaultValue],
* stores its result back into the map as well as returns it.
*
* In a way, this is a sort of simple cache, where a new value is recomputed
* if the previous one has been deleted.
*
* @see MutableMap.getOrPut Equivalent method for regular maps.
*/
@ExperimentalWeakApi
inline fun WeakMap.getOrPut(key: K, defaultValue: () -> V): V =
get(key) ?: run {
val new = defaultValue()
set(key, new)
new
}
// endregion
// region Delegation syntax for string-based access
/**
* Allows to use a weak map for data-oriented usage.
*
* ### Example
*
* ```kotlin
* val map = WeakMap()
*
* var score by map
* var age by map
*
* score = 5
* println(age)
* ```
*
* @see Map.getValue Equivalent method for regular maps.
*/
@ExperimentalWeakApi
inline operator fun WeakMap.getValue(thisRef: Any?, property: KProperty<*>): V? =
get(property.name)
/**
* Allows to use a weak map for data-oriented usage.
*
* ### Example
*
* ```kotlin
* val map = WeakMap()
*
* var score by map
* var age by map
*
* score = 5
* println(age)
* ```
*
* @see MutableMap.setValue Equivalent method for regular maps.
*/
@ExperimentalWeakApi
inline operator fun WeakMap.setValue(thisRef: Any?, property: KProperty<*>, value: V) {
set(property.name, value)
}
// endregion
// region Collection helpers
/**
* Sets all the values from the provided map into the current one.
*
* @see MutableMap.putAll Equivalent method for regular maps.
*/
@ExperimentalWeakApi
fun WeakMap.setAll(from: Map) {
for ((k, v) in from) {
set(k, v)
}
}
/**
* Removes the specified keys from this map.
*/
@ExperimentalWeakApi
fun WeakMap.removeAll(from: Iterable) {
for (k in from) {
remove(k)
}
}
/**
* Removes the specified associations from this map.
*/
@ExperimentalWeakApi
fun WeakMap.removeAll(from: Map) {
for ((k, v) in from) {
remove(k, v)
}
}
// endregion
// region Other extensions
/**
* Removes the association of [key] to [value] from this map.
*
* If [key] is associated to another value than [value], nothing happens.
*/
@ExperimentalWeakApi
fun WeakMap.remove(key: K, value: V) {
if (get(key) == value) {
remove(key)
}
}
// endregion
© 2015 - 2025 Weber Informatics LLC | Privacy Policy