Prepare to treat keys mapped to null same way as missing keys in Map extensions: getOrElse, getOrPut, getOrImplicitDefault.

This commit is contained in:
Ilya Gorbunov
2015-12-17 07:52:41 +03:00
parent 8b5a194dd6
commit 188119aa83
6 changed files with 60 additions and 9 deletions
@@ -12,6 +12,15 @@ import java.util.*
*
* @throws NoSuchElementException when the map doesn't contain value for the specified key and no implicit default was provided for that map.
*/
public fun <K, V: Any> Map<K, V>.getOrImplicitDefault(key: K): V {
if (this is MapWithDefault)
return this.getOrImplicitDefault(key)
return getOrElse(key, { throw NoSuchElementException("Key $key is missing in the map.") })
}
@kotlin.jvm.JvmName("getOrImplicitDefaultNullable")
@Deprecated("This function will change its behavior soon not to distinguish missing keys and keys mapped to nulls.")
public fun <K, V> Map<K, V>.getOrImplicitDefault(key: K): V {
if (this is MapWithDefault)
return this.getOrImplicitDefault(key)
@@ -179,6 +179,7 @@ public fun <K, V> Map.Entry<K, V>.toPair(): Pair<K, V> = Pair(key, value)
*
* @sample test.collections.MapTest.getOrElse
*/
@Deprecated("This function will change its behavior soon not to distinguish missing keys and keys mapped to nulls. To stick with the new behavior you can use get(key) with ?: operator after instead.")
public inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V {
val value = get(key)
if (value == null && !containsKey(key)) {
@@ -194,14 +195,30 @@ public inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V {
*
* @sample test.collections.MapTest.getOrPut
*/
public inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
@kotlin.jvm.JvmVersion
public inline fun <K, V: Any> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
val value = get(key)
if (value == null && !containsKey(key)) {
return if (value == null) {
val answer = defaultValue()
put(key, answer)
return answer
answer
} else {
return value as V
value
}
}
@kotlin.jvm.JvmName("getOrPutNullable")
@kotlin.jvm.JvmVersion
@Deprecated("This function will change its behavior soon not to distinguish missing keys and keys mapped to nulls.")
@kotlin.internal.LowPriorityInOverloadResolution
public inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
val value = get(key)
return if (value == null && !containsKey(key)) {
val answer = defaultValue()
put(key, answer)
answer
} else {
value as V
}
}
@@ -27,6 +27,7 @@ public fun <K, V> MutableMap<K, V>.set(key: K, value: V): V? = put(key, value)
* Use [concurrentGetOrPut] instead, or cast this to a [MutableMap] if you want to sacrifice the concurrent-safety.
*/
@Deprecated("Use concurrentGetOrPut instead or cast this map to MutableMap.", level = DeprecationLevel.ERROR)
@kotlin.internal.LowPriorityInOverloadResolution
public inline fun <K, V> ConcurrentMap<K, V>.getOrPut(key: K, defaultValue: () -> V): Nothing =
throw UnsupportedOperationException("getOrPut is not supported on ConcurrentMap.")
@@ -39,13 +40,20 @@ public inline fun <K, V> ConcurrentMap<K, V>.getOrPut(key: K, defaultValue: () -
* This method guarantees not to put the value into the map if the key is already there,
* but the [defaultValue] function may be invoked even if the key is already in the map.
*/
public inline fun <K, V: Any> ConcurrentMap<K, V>.concurrentGetOrPut(key: K, defaultValue: () -> V): V {
public inline fun <K, V: Any> ConcurrentMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
// Do not use computeIfAbsent on JVM8 as it would change locking behavior
return this.get(key) ?:
defaultValue().let { default -> this.putIfAbsent(key, default) ?: default }
}
@Deprecated("Use getOrPut instead", ReplaceWith("getOrPut(key, defaultValue)"))
public inline fun <K, V: Any> ConcurrentMap<K, V>.concurrentGetOrPut(key: K, defaultValue: () -> V): V {
// Do not use computeIfAbsent on JVM8 as it would change locking behavior
return this.get(key) ?:
defaultValue().let { default -> this.putIfAbsent(key, default) ?: default }
}
/**
* Converts this [Map] to a [SortedMap] so iteration order will be in key order.
*