Map.getOrElse: treat nulls as missing values.

This commit is contained in:
Ilya Gorbunov
2016-01-22 07:33:27 +03:00
parent 90a239e74c
commit a49db730a9
3 changed files with 19 additions and 5 deletions
@@ -17,7 +17,7 @@ public fun <K, V: Any> Map<K, V>.getOrImplicitDefault(key: K): V {
if (this is MapWithDefault) if (this is MapWithDefault)
return this.getOrImplicitDefault(key) return this.getOrImplicitDefault(key)
return getOrElse(key, { throw NoSuchElementException("Key $key is missing in the map.") }) return getOrElseNullable(key, { throw NoSuchElementException("Key $key is missing in the map.") })
} }
@kotlin.jvm.JvmName("getOrImplicitDefaultNullable") @kotlin.jvm.JvmName("getOrImplicitDefaultNullable")
@@ -26,7 +26,7 @@ public fun <K, V> Map<K, V>.getOrImplicitDefault(key: K): V {
if (this is MapWithDefault) if (this is MapWithDefault)
return this.getOrImplicitDefault(key) return this.getOrImplicitDefault(key)
return getOrElse(key, { throw NoSuchElementException("Key $key is missing in the map.") }) return getOrElseNullable(key, { throw NoSuchElementException("Key $key is missing in the map.") })
} }
/** /**
@@ -83,7 +83,7 @@ private class MapWithDefaultImpl<K, out V>(public override val map: Map<K,V>, pr
override val values: Collection<V> get() = map.values override val values: Collection<V> get() = map.values
override val entries: Set<Map.Entry<K, V>> get() = map.entries override val entries: Set<Map.Entry<K, V>> get() = map.entries
override fun getOrImplicitDefault(key: K): V = map.getOrElse(key, { default(key) }) override fun getOrImplicitDefault(key: K): V = map.getOrElseNullable(key, { default(key) })
} }
private class MutableMapWithDefaultImpl<K, V>(public override val map: MutableMap<K, V>, private val default: (key: K) -> V): MutableMapWithDefault<K, V> { private class MutableMapWithDefaultImpl<K, V>(public override val map: MutableMap<K, V>, private val default: (key: K) -> V): MutableMapWithDefault<K, V> {
@@ -104,6 +104,6 @@ private class MutableMapWithDefaultImpl<K, V>(public override val map: MutableMa
override fun putAll(m: Map<out K, V>) = map.putAll(m) override fun putAll(m: Map<out K, V>) = map.putAll(m)
override fun clear() = map.clear() override fun clear() = map.clear()
override fun getOrImplicitDefault(key: K): V = map.getOrElse(key, { default(key) }) override fun getOrImplicitDefault(key: K): V = map.getOrElseNullable(key, { default(key) })
} }
@@ -170,8 +170,16 @@ public fun <K, V> Map.Entry<K, V>.toPair(): Pair<K, V> = Pair(key, value)
* *
* @sample test.collections.MapTest.getOrElse * @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 { public inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V {
val value = get(key)
if (value == null) {
return defaultValue()
} else {
return value
}
}
internal inline fun <K, V> Map<K, V>.getOrElseNullable(key: K, defaultValue: () -> V): V {
val value = get(key) val value = get(key)
if (value == null && !containsKey(key)) { if (value == null && !containsKey(key)) {
return defaultValue() return defaultValue()
@@ -180,6 +188,8 @@ public inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V {
} }
} }
/** /**
* Returns the value for the given key. If the key is not found in the map, calls the [defaultValue] function, * Returns the value for the given key. If the key is not found in the map, calls the [defaultValue] function,
* puts its result into the map under the given key and returns it. * puts its result into the map under the given key and returns it.
@@ -20,6 +20,10 @@ class MapTest {
val empty = mapOf<String, Int?>() val empty = mapOf<String, Int?>()
val c = empty.getOrElse("") { null } val c = empty.getOrElse("") { null }
assertEquals(null, c) assertEquals(null, c)
val nullable = mapOf(1 to null)
val d = nullable.getOrElse(1) { "x" }
assertEquals("x", d)
} }
@test fun getOrImplicitDefault() { @test fun getOrImplicitDefault() {