commonMain.kotlin.collections.Maps.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-stdlib Show documentation
Show all versions of kotlin-stdlib Show documentation
Kotlin Standard Library for JVM
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:kotlin.jvm.JvmMultifileClass
@file:kotlin.jvm.JvmName("MapsKt")
@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class)
package kotlin.collections
import kotlin.contracts.*
private object EmptyMap : Map, Serializable {
private const val serialVersionUID: Long = 8246714829545688274
override fun equals(other: Any?): Boolean = other is Map<*, *> && other.isEmpty()
override fun hashCode(): Int = 0
override fun toString(): String = "{}"
override val size: Int get() = 0
override fun isEmpty(): Boolean = true
override fun containsKey(key: Any?): Boolean = false
override fun containsValue(value: Nothing): Boolean = false
override fun get(key: Any?): Nothing? = null
override val entries: Set> get() = EmptySet
override val keys: Set get() = EmptySet
override val values: Collection get() = EmptyList
private fun readResolve(): Any = EmptyMap
}
/**
* Returns an empty read-only map of specified type.
*
* The returned map is serializable (JVM).
* @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap
*/
public fun emptyMap(): Map = @Suppress("UNCHECKED_CAST") (EmptyMap as Map)
/**
* Returns a new read-only map with the specified contents, given as a list of pairs
* where the first value is the key and the second is the value.
*
* If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.
*
* Entries of the map are iterated in the order they were specified.
*
* The returned map is serializable (JVM).
*
* @sample samples.collections.Maps.Instantiation.mapFromPairs
*/
public fun mapOf(vararg pairs: Pair): Map =
if (pairs.size > 0) pairs.toMap(LinkedHashMap(mapCapacity(pairs.size))) else emptyMap()
/**
* Returns a new read-only map, mapping only the specified key to the
* specified value.
*
* The returned map is serializable (JVM).
*
* @sample samples.collections.Maps.Instantiation.mapFromPairs
*/
@SinceKotlin("1.9")
public expect fun mapOf(pair: Pair): Map
/**
* Returns an empty read-only map.
*
* The returned map is serializable (JVM).
* @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap
*/
@kotlin.internal.InlineOnly
public inline fun mapOf(): Map = emptyMap()
/**
* Returns an empty new [MutableMap].
*
* The returned map preserves the entry iteration order.
* @sample samples.collections.Maps.Instantiation.emptyMutableMap
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun mutableMapOf(): MutableMap = LinkedHashMap()
/**
* Returns a new [MutableMap] with the specified contents, given as a list of pairs
* where the first component is the key and the second is the value.
*
* If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.
*
* Entries of the map are iterated in the order they were specified.
*
* @sample samples.collections.Maps.Instantiation.mutableMapFromPairs
* @sample samples.collections.Maps.Instantiation.emptyMutableMap
*/
public fun mutableMapOf(vararg pairs: Pair): MutableMap =
LinkedHashMap(mapCapacity(pairs.size)).apply { putAll(pairs) }
/**
* Returns an empty new [HashMap].
*
* @sample samples.collections.Maps.Instantiation.emptyHashMap
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun hashMapOf(): HashMap = HashMap()
/**
* Returns a new [HashMap] with the specified contents, given as a list of pairs
* where the first component is the key and the second is the value.
*
* @sample samples.collections.Maps.Instantiation.hashMapFromPairs
*/
public fun hashMapOf(vararg pairs: Pair): HashMap = HashMap(mapCapacity(pairs.size)).apply { putAll(pairs) }
/**
* Returns an empty new [LinkedHashMap].
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun linkedMapOf(): LinkedHashMap = LinkedHashMap()
/**
* Returns a new [LinkedHashMap] with the specified contents, given as a list of pairs
* where the first component is the key and the second is the value.
*
* If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.
*
* Entries of the map are iterated in the order they were specified.
*
* @sample samples.collections.Maps.Instantiation.linkedMapFromPairs
*/
public fun linkedMapOf(vararg pairs: Pair): LinkedHashMap = pairs.toMap(LinkedHashMap(mapCapacity(pairs.size)))
/**
* Builds a new read-only [Map] by populating a [MutableMap] using the given [builderAction]
* and returning a read-only map with the same key-value pairs.
*
* The map passed as a receiver to the [builderAction] is valid only inside that function.
* Using it outside of the function produces an unspecified behavior.
*
* Entries of the map are iterated in the order they were added by the [builderAction].
*
* The returned map is serializable (JVM).
*
* @sample samples.collections.Builders.Maps.buildMapSample
*/
@SinceKotlin("1.6")
@WasExperimental(ExperimentalStdlibApi::class)
@kotlin.internal.InlineOnly
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
public inline fun buildMap(@BuilderInference builderAction: MutableMap.() -> Unit): Map {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return buildMapInternal(builderAction)
}
@PublishedApi
@SinceKotlin("1.3")
@kotlin.internal.InlineOnly
internal expect inline fun buildMapInternal(builderAction: MutableMap.() -> Unit): Map
/**
* Builds a new read-only [Map] by populating a [MutableMap] using the given [builderAction]
* and returning a read-only map with the same key-value pairs.
*
* The map passed as a receiver to the [builderAction] is valid only inside that function.
* Using it outside of the function produces an unspecified behavior.
*
* [capacity] is used to hint the expected number of pairs added in the [builderAction].
*
* Entries of the map are iterated in the order they were added by the [builderAction].
*
* The returned map is serializable (JVM).
*
* @throws IllegalArgumentException if the given [capacity] is negative.
*
* @sample samples.collections.Builders.Maps.buildMapSample
*/
@SinceKotlin("1.6")
@WasExperimental(ExperimentalStdlibApi::class)
@kotlin.internal.InlineOnly
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
public inline fun buildMap(capacity: Int, @BuilderInference builderAction: MutableMap.() -> Unit): Map {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return buildMapInternal(capacity, builderAction)
}
@PublishedApi
@SinceKotlin("1.3")
@kotlin.internal.InlineOnly
internal expect inline fun buildMapInternal(capacity: Int, builderAction: MutableMap.() -> Unit): Map
/**
* Calculate the initial capacity of a map.
*/
@PublishedApi
internal expect fun mapCapacity(expectedSize: Int): Int
/**
* Returns `true` if this map is not empty.
* @sample samples.collections.Maps.Usage.mapIsNotEmpty
*/
@kotlin.internal.InlineOnly
public inline fun Map.isNotEmpty(): Boolean = !isEmpty()
/**
* Returns `true` if this nullable map is either null or empty.
* @sample samples.collections.Maps.Usage.mapIsNullOrEmpty
*/
@SinceKotlin("1.3")
@kotlin.internal.InlineOnly
public inline fun Map?.isNullOrEmpty(): Boolean {
contract {
returns(false) implies (this@isNullOrEmpty != null)
}
return this == null || isEmpty()
}
/**
* Returns the [Map] if its not `null`, or the empty [Map] otherwise.
*
* @sample samples.collections.Maps.Usage.mapOrEmpty
*/
@kotlin.internal.InlineOnly
public inline fun Map?.orEmpty(): Map = this ?: emptyMap()
/**
* Returns this map if it's not empty
* or the result of calling [defaultValue] function if the map is empty.
*
* @sample samples.collections.Maps.Usage.mapIfEmpty
*/
@SinceKotlin("1.3")
@kotlin.internal.InlineOnly
public inline fun M.ifEmpty(defaultValue: () -> R): R where M : Map<*, *>, M : R {
contract {
callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE)
}
return if (isEmpty()) defaultValue() else this
}
/**
* Checks if the map contains the given key.
*
* This method allows to use the `x in map` syntax for checking whether an object is contained in the map.
*
* @sample samples.collections.Maps.Usage.containsKey
*/
@kotlin.internal.InlineOnly
public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.contains(key: K): Boolean = containsKey(key)
/**
* Returns the value corresponding to the given [key], or `null` if such a key is not present in the map.
*/
@kotlin.internal.InlineOnly
public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.get(key: K): V? =
@Suppress("UNCHECKED_CAST") (this as Map).get(key)
/**
* Allows to use the index operator for storing values in a mutable map.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.set(key: K, value: V): Unit {
put(key, value)
}
/**
* Returns `true` if the map contains the specified [key].
*
* Allows to overcome type-safety restriction of `containsKey` that requires to pass a key of type `K`.
*/
@kotlin.internal.InlineOnly
public inline fun <@kotlin.internal.OnlyInputTypes K> Map.containsKey(key: K): Boolean =
@Suppress("UNCHECKED_CAST") (this as Map).containsKey(key)
/**
* Returns `true` if the map maps one or more keys to the specified [value].
*
* Allows to overcome type-safety restriction of `containsValue` that requires to pass a value of type `V`.
*
* @sample samples.collections.Maps.Usage.containsValue
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") // false warning, extension takes precedence in some cases
@kotlin.internal.InlineOnly
public inline fun Map.containsValue(value: V): Boolean = this.containsValue(value)
/**
* Removes the specified key and its corresponding value from this map.
*
* @return the previous value associated with the key, or `null` if the key was not present in the map.
* Allows to overcome type-safety restriction of `remove` that requires to pass a key of type `K`.
*/
@kotlin.internal.InlineOnly
public inline fun <@kotlin.internal.OnlyInputTypes K, V> MutableMap.remove(key: K): V? =
@Suppress("UNCHECKED_CAST") (this as MutableMap).remove(key)
/**
* Returns the key component of the map entry.
*
* This method allows to use destructuring declarations when working with maps, for example:
* ```
* for ((key, value) in map) {
* // do something with the key and the value
* }
* ```
*/
@kotlin.internal.InlineOnly
public inline operator fun Map.Entry.component1(): K = key
/**
* Returns the value component of the map entry.
*
* This method allows to use destructuring declarations when working with maps, for example:
* ```
* for ((key, value) in map) {
* // do something with the key and the value
* }
* ```
*/
@kotlin.internal.InlineOnly
public inline operator fun Map.Entry.component2(): V = value
/**
* Converts entry to [Pair] with key being first component and value being second.
*/
@kotlin.internal.InlineOnly
public inline fun Map.Entry.toPair(): Pair = Pair(key, value)
/**
* Returns the value for the given [key] if the value is present and not `null`.
* Otherwise, returns the result of the [defaultValue] function.
*
* @sample samples.collections.Maps.Usage.getOrElse
*/
@kotlin.internal.InlineOnly
public inline fun Map.getOrElse(key: K, defaultValue: () -> V): V {
contract {
callsInPlace(defaultValue, InvocationKind.AT_MOST_ONCE)
}
return get(key) ?: defaultValue()
}
internal inline fun Map.getOrElseNullable(key: K, defaultValue: () -> V): V {
val value = get(key)
if (value == null && !containsKey(key)) {
return defaultValue()
} else {
@Suppress("UNCHECKED_CAST")
return value as V
}
}
/**
* Returns the value for the given [key] or throws an exception if there is no such key in the map.
*
* If the map was created by [withDefault], resorts to its `defaultValue` provider function
* instead of throwing an exception.
*
* @throws NoSuchElementException when the map doesn't contain a value for the specified key and
* no implicit default value was provided for that map.
*/
@SinceKotlin("1.1")
public fun Map.getValue(key: K): V = getOrImplicitDefault(key)
/**
* Returns the value for the given [key] if the value is present and not `null`.
* Otherwise, calls the [defaultValue] function,
* puts its result into the map under the given key and returns the call result.
*
* Note that the operation is not guaranteed to be atomic if the map is being modified concurrently.
*
* @sample samples.collections.Maps.Usage.getOrPut
*/
public inline fun MutableMap.getOrPut(key: K, defaultValue: () -> V): V {
val value = get(key)
return if (value == null) {
val answer = defaultValue()
put(key, answer)
answer
} else {
value
}
}
/**
* Returns an [Iterator] over the entries in the [Map].
*
* @sample samples.collections.Maps.Usage.forOverEntries
*/
@kotlin.internal.InlineOnly
public inline operator fun Map.iterator(): Iterator> = entries.iterator()
/**
* Returns a [MutableIterator] over the mutable entries in the [MutableMap].
*
*/
@kotlin.jvm.JvmName("mutableIterator")
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.iterator(): MutableIterator> = entries.iterator()
/**
* Populates the given [destination] map with entries having the keys of this map and the values obtained
* by applying the [transform] function to each entry in this [Map].
*/
public inline fun > Map.mapValuesTo(destination: M, transform: (Map.Entry) -> R): M {
return entries.associateByTo(destination, { it.key }, transform)
}
/**
* Populates the given [destination] map with entries having the keys obtained
* by applying the [transform] function to each entry in this [Map] and the values of this map.
*
* In case if any two entries are mapped to the equal keys, the value of the latter one will overwrite
* the value associated with the former one.
*/
public inline fun > Map.mapKeysTo(destination: M, transform: (Map.Entry) -> R): M {
return entries.associateByTo(destination, transform, { it.value })
}
/**
* Puts all the given [pairs] into this [MutableMap] with the first component in the pair being the key and the second the value.
*/
public fun MutableMap.putAll(pairs: Array>): Unit {
for ((key, value) in pairs) {
put(key, value)
}
}
/**
* Puts all the elements of the given collection into this [MutableMap] with the first component in the pair being the key and the second the value.
*/
public fun MutableMap.putAll(pairs: Iterable>): Unit {
for ((key, value) in pairs) {
put(key, value)
}
}
/**
* Puts all the elements of the given sequence into this [MutableMap] with the first component in the pair being the key and the second the value.
*/
public fun MutableMap.putAll(pairs: Sequence>): Unit {
for ((key, value) in pairs) {
put(key, value)
}
}
/**
* Returns a new map with entries having the keys of this map and the values obtained by applying the [transform]
* function to each entry in this [Map].
*
* The returned map preserves the entry iteration order of the original map.
*
* @sample samples.collections.Maps.Transformations.mapValues
*/
public inline fun Map.mapValues(transform: (Map.Entry) -> R): Map {
return mapValuesTo(LinkedHashMap(mapCapacity(size)), transform) // .optimizeReadOnlyMap()
}
/**
* Returns a new Map with entries having the keys obtained by applying the [transform] function to each entry in this
* [Map] and the values of this map.
*
* In case if any two entries are mapped to the equal keys, the value of the latter one will overwrite
* the value associated with the former one.
*
* The returned map preserves the entry iteration order of the original map.
*
* @sample samples.collections.Maps.Transformations.mapKeys
*/
public inline fun Map.mapKeys(transform: (Map.Entry) -> R): Map {
return mapKeysTo(LinkedHashMap(mapCapacity(size)), transform) // .optimizeReadOnlyMap()
}
/**
* Returns a map containing all key-value pairs with keys matching the given [predicate].
*
* The returned map preserves the entry iteration order of the original map.
* @sample samples.collections.Maps.Filtering.filterKeys
*/
public inline fun Map.filterKeys(predicate: (K) -> Boolean): Map {
val result = LinkedHashMap()
for (entry in this) {
if (predicate(entry.key)) {
result.put(entry.key, entry.value)
}
}
return result
}
/**
* Returns a map containing all key-value pairs with values matching the given [predicate].
*
* The returned map preserves the entry iteration order of the original map.
* @sample samples.collections.Maps.Filtering.filterValues
*/
public inline fun Map.filterValues(predicate: (V) -> Boolean): Map {
val result = LinkedHashMap()
for (entry in this) {
if (predicate(entry.value)) {
result.put(entry.key, entry.value)
}
}
return result
}
/**
* Appends all entries matching the given [predicate] into the mutable map given as [destination] parameter.
*
* @return the destination map.
* @sample samples.collections.Maps.Filtering.filterTo
*/
public inline fun > Map.filterTo(destination: M, predicate: (Map.Entry) -> Boolean): M {
for (element in this) {
if (predicate(element)) {
destination.put(element.key, element.value)
}
}
return destination
}
/**
* Returns a new map containing all key-value pairs matching the given [predicate].
*
* The returned map preserves the entry iteration order of the original map.
* @sample samples.collections.Maps.Filtering.filter
*/
public inline fun Map.filter(predicate: (Map.Entry) -> Boolean): Map {
return filterTo(LinkedHashMap(), predicate)
}
/**
* Appends all entries not matching the given [predicate] into the given [destination].
*
* @return the destination map.
* @sample samples.collections.Maps.Filtering.filterNotTo
*/
public inline fun > Map.filterNotTo(destination: M, predicate: (Map.Entry) -> Boolean): M {
for (element in this) {
if (!predicate(element)) {
destination.put(element.key, element.value)
}
}
return destination
}
/**
* Returns a new map containing all key-value pairs not matching the given [predicate].
*
* The returned map preserves the entry iteration order of the original map.
* @sample samples.collections.Maps.Filtering.filterNot
*/
public inline fun Map.filterNot(predicate: (Map.Entry) -> Boolean): Map {
return filterNotTo(LinkedHashMap(), predicate)
}
/**
* Returns a new map containing all key-value pairs from the given collection of pairs.
*
* The returned map preserves the entry iteration order of the original collection.
* If any of two pairs would have the same key the last one gets added to the map.
*/
public fun Iterable>.toMap(): Map {
if (this is Collection) {
return when (size) {
0 -> emptyMap()
1 -> mapOf(if (this is List) this[0] else iterator().next())
else -> toMap(LinkedHashMap(mapCapacity(size)))
}
}
return toMap(LinkedHashMap()).optimizeReadOnlyMap()
}
/**
* Populates and returns the [destination] mutable map with key-value pairs from the given collection of pairs.
*/
public fun > Iterable>.toMap(destination: M): M =
destination.apply { putAll(this@toMap) }
/**
* Returns a new map containing all key-value pairs from the given array of pairs.
*
* The returned map preserves the entry iteration order of the original array.
* If any of two pairs would have the same key the last one gets added to the map.
*/
public fun Array>.toMap(): Map = when (size) {
0 -> emptyMap()
1 -> mapOf(this[0])
else -> toMap(LinkedHashMap(mapCapacity(size)))
}
/**
* Populates and returns the [destination] mutable map with key-value pairs from the given array of pairs.
*/
public fun > Array>.toMap(destination: M): M =
destination.apply { putAll(this@toMap) }
/**
* Returns a new map containing all key-value pairs from the given sequence of pairs.
*
* The returned map preserves the entry iteration order of the original sequence.
* If any of two pairs would have the same key the last one gets added to the map.
*/
public fun Sequence>.toMap(): Map = toMap(LinkedHashMap()).optimizeReadOnlyMap()
/**
* Populates and returns the [destination] mutable map with key-value pairs from the given sequence of pairs.
*/
public fun > Sequence>.toMap(destination: M): M =
destination.apply { putAll(this@toMap) }
/**
* Returns a new read-only map containing all key-value pairs from the original map.
*
* The returned map preserves the entry iteration order of the original map.
*/
@SinceKotlin("1.1")
public fun Map.toMap(): Map = when (size) {
0 -> emptyMap()
1 -> toSingletonMap()
else -> toMutableMap()
}
/**
* Returns a new mutable map containing all key-value pairs from the original map.
*
* The returned map preserves the entry iteration order of the original map.
*/
@SinceKotlin("1.1")
public fun Map.toMutableMap(): MutableMap = LinkedHashMap(this)
/**
* Populates and returns the [destination] mutable map with key-value pairs from the given map.
*/
@SinceKotlin("1.1")
public fun > Map.toMap(destination: M): M =
destination.apply { putAll(this@toMap) }
/**
* Creates a new read-only map by replacing or adding an entry to this map from a given key-value [pair].
*
* The returned map preserves the entry iteration order of the original map.
* The [pair] is iterated in the end if it has a unique key.
*/
public operator fun Map.plus(pair: Pair): Map =
if (this.isEmpty()) mapOf(pair) else LinkedHashMap(this).apply { put(pair.first, pair.second) }
/**
* Creates a new read-only map by replacing or adding entries to this map from a given collection of key-value [pairs].
*
* The returned map preserves the entry iteration order of the original map.
* Those [pairs] with unique keys are iterated in the end in the order of [pairs] collection.
*/
public operator fun Map.plus(pairs: Iterable>): Map =
if (this.isEmpty()) pairs.toMap() else LinkedHashMap(this).apply { putAll(pairs) }
/**
* Creates a new read-only map by replacing or adding entries to this map from a given array of key-value [pairs].
*
* The returned map preserves the entry iteration order of the original map.
* Those [pairs] with unique keys are iterated in the end in the order of [pairs] array.
*/
public operator fun Map.plus(pairs: Array>): Map =
if (this.isEmpty()) pairs.toMap() else LinkedHashMap(this).apply { putAll(pairs) }
/**
* Creates a new read-only map by replacing or adding entries to this map from a given sequence of key-value [pairs].
*
* The returned map preserves the entry iteration order of the original map.
* Those [pairs] with unique keys are iterated in the end in the order of [pairs] sequence.
*/
public operator fun Map.plus(pairs: Sequence>): Map =
LinkedHashMap(this).apply { putAll(pairs) }.optimizeReadOnlyMap()
/**
* Creates a new read-only map by replacing or adding entries to this map from another [map].
*
* The returned map preserves the entry iteration order of the original map.
* Those entries of another [map] that are missing in this map are iterated in the end in the order of that [map].
*/
public operator fun Map.plus(map: Map): Map =
LinkedHashMap(this).apply { putAll(map) }
/**
* Appends or replaces the given [pair] in this mutable map.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.plusAssign(pair: Pair) {
put(pair.first, pair.second)
}
/**
* Appends or replaces all pairs from the given collection of [pairs] in this mutable map.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.plusAssign(pairs: Iterable>) {
putAll(pairs)
}
/**
* Appends or replaces all pairs from the given array of [pairs] in this mutable map.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.plusAssign(pairs: Array>) {
putAll(pairs)
}
/**
* Appends or replaces all pairs from the given sequence of [pairs] in this mutable map.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.plusAssign(pairs: Sequence>) {
putAll(pairs)
}
/**
* Appends or replaces all entries from the given [map] in this mutable map.
*/
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.plusAssign(map: Map) {
putAll(map)
}
/**
* Returns a map containing all entries of the original map except the entry with the given [key].
*
* The returned map preserves the entry iteration order of the original map.
*/
@SinceKotlin("1.1")
public operator fun Map.minus(key: K): Map =
this.toMutableMap().apply { minusAssign(key) }.optimizeReadOnlyMap()
/**
* Returns a map containing all entries of the original map except those entries
* the keys of which are contained in the given [keys] collection.
*
* The returned map preserves the entry iteration order of the original map.
*/
@SinceKotlin("1.1")
public operator fun Map.minus(keys: Iterable): Map =
this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap()
/**
* Returns a map containing all entries of the original map except those entries
* the keys of which are contained in the given [keys] array.
*
* The returned map preserves the entry iteration order of the original map.
*/
@SinceKotlin("1.1")
public operator fun Map.minus(keys: Array): Map =
this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap()
/**
* Returns a map containing all entries of the original map except those entries
* the keys of which are contained in the given [keys] sequence.
*
* The returned map preserves the entry iteration order of the original map.
*/
@SinceKotlin("1.1")
public operator fun Map.minus(keys: Sequence): Map =
this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap()
/**
* Removes the entry with the given [key] from this mutable map.
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.minusAssign(key: K) {
remove(key)
}
/**
* Removes all entries the keys of which are contained in the given [keys] collection from this mutable map.
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.minusAssign(keys: Iterable) {
this.keys.removeAll(keys)
}
/**
* Removes all entries the keys of which are contained in the given [keys] array from this mutable map.
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.minusAssign(keys: Array) {
this.keys.removeAll(keys)
}
/**
* Removes all entries from the keys of which are contained in the given [keys] sequence from this mutable map.
*/
@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline operator fun MutableMap.minusAssign(keys: Sequence) {
this.keys.removeAll(keys)
}
// do not expose for now @PublishedApi
internal fun Map.optimizeReadOnlyMap() = when (size) {
0 -> emptyMap()
1 -> toSingletonMapOrSelf()
else -> this
}