From 3954215b506c9c495390187bfc64c4c86a435065 Mon Sep 17 00:00:00 2001 From: Laszlo Hornyak Date: Sat, 10 Jan 2015 12:43:27 +0100 Subject: [PATCH] Add support for + and - operators in immutable maps #KT-6594 Fixed --- .../stdlib/src/kotlin/collections/Maps.kt | 62 +++++++++- libraries/stdlib/test/collections/MapTest.kt | 113 +++++++++++++++++- 2 files changed, 173 insertions(+), 2 deletions(-) diff --git a/libraries/stdlib/src/kotlin/collections/Maps.kt b/libraries/stdlib/src/kotlin/collections/Maps.kt index d75be9bc2ca..d2148da4f5d 100644 --- a/libraries/stdlib/src/kotlin/collections/Maps.kt +++ b/libraries/stdlib/src/kotlin/collections/Maps.kt @@ -285,12 +285,26 @@ public inline fun Map.filterNot(predicate: (Map.Entry) -> Boo } /** - * Appends given [pair] to the mutable map. + * Appends or replaces the given [pair] in this mutable map. */ public 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. + */ +public fun MutableMap.plusAssign(pairs: Iterable>) { + putAll(pairs) +} + +/** + * Appends or replaces all entries from the given [map] in this mutable map. + */ +public fun MutableMap.plusAssign(map: Map) { + putAll(map) +} + /** * Returns a new map containing all key-value pairs from the given collection of pairs. */ @@ -306,3 +320,49 @@ public fun Iterable>.toMap(): Map { * Converts this [Map] to a [LinkedHashMap], maintaining the insertion order of elements added to that map afterwards. */ public fun Map.toLinkedMap(): MutableMap = LinkedHashMap(this) + +/** + * Creates a new read-only map by replacing or adding an entry to this map from a given key-value [pair] + */ +public fun Map.plus(pair: Pair): Map { + val newMap = this.toLinkedMap() + newMap.put(pair.first, pair.second) + return newMap +} + +/** + * Creates a new read-only map by replacing or adding entries to this map from a given collection of key-value [pairs] + */ +public fun Map.plus(pairs: Iterable>): Map { + val newMap = this.toLinkedMap() + newMap.putAll(pairs) + return newMap +} + +/** + * Creates a new read-only map by replacing or adding entries to this map from another [map] + */ +public fun Map.plus(map: Map): Map { + val newMap = this.toLinkedMap() + newMap.putAll(map) + return newMap +} + +/** + * Creates a new read-only map by removing a key from this map + */ +public fun Map.minus(key: K): Map { + return this.filterKeys { key != it } +} + +/** + * Creates a new read-only map by removing a collection of keys from this map + */ +public fun Map.minus(keys: Iterable): Map { + val result = LinkedHashMap() + result.putAll(this) + for (entry in keys) { + result.remove(entry) + } + return result +} \ No newline at end of file diff --git a/libraries/stdlib/test/collections/MapTest.kt b/libraries/stdlib/test/collections/MapTest.kt index e02bbe175a1..9eb6e473711 100644 --- a/libraries/stdlib/test/collections/MapTest.kt +++ b/libraries/stdlib/test/collections/MapTest.kt @@ -1,6 +1,8 @@ package test.collections -import kotlin.test.* +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue import org.junit.Test as test class MapTest { @@ -236,4 +238,113 @@ class MapTest { assertEquals(2, extended["c"]) assertEquals(3, extended["b"]) } + + test fun plusAssignList() { + val extended = hashMapOf(Pair("b", 3)) + extended += listOf("C" to 3, "D" to 4) + assertEquals(3, extended.size()) + assertEquals(3, extended["C"]) + assertEquals(4, extended["D"]) + } + + test fun plusAssignMap() { + val extended = hashMapOf(Pair("b", 3)) + extended += mapOf("C" to 3, "D" to 4) + assertEquals(3, extended.size()) + assertEquals(3, extended["C"]) + assertEquals(4, extended["D"]) + } + + test fun plus() { + val original = mapOf("A" to 1, "B" to 2) + val extended = original + ("C" to 3) + assertEquals(extended["A"], 1) + assertEquals(extended["B"], 2) + assertEquals(extended["C"], 3) + } + + test fun plusList() { + val original = mapOf("A" to 1, "B" to 2) + val extended = original + listOf("C" to 3, "D" to 4) + assertEquals(extended["A"], 1) + assertEquals(extended["B"], 2) + assertEquals(extended["C"], 3) + assertEquals(extended["D"], 4) + } + + test fun plusMap() { + val original = mapOf("A" to 1, "B" to 2) + val extended = original + mapOf("C" to 3, "D" to 4) + assertEquals(extended["A"], 1) + assertEquals(extended["B"], 2) + assertEquals(extended["C"], 3) + assertEquals(extended["D"], 4) + } + + test fun plusListOverload() { + val original = mapOf("A" to 1, "B" to 2) + val extended = original + listOf("B" to 3, "C" to 4) + assertEquals(extended["A"], 1) + assertEquals(extended["B"], 3) + assertEquals(extended["C"], 4) + } + + test fun plusEmptyList() { + val original = mapOf("A" to 1, "B" to 2) + val extended = original + listOf() + assertEquals(extended["A"], 1) + assertEquals(extended["B"], 2) + } + + test fun plusEmptySet() { + val original = mapOf("A" to 1, "B" to 2) + val extended = original + setOf() + assertEquals(extended["A"], 1) + assertEquals(extended["B"], 2) + } + + test fun minus() { + val original = mapOf("A" to 1, "B" to 2) + val shortened = original - "B" + assertEquals(shortened["A"], 1) + assertFalse(shortened.contains("B")) + } + + test fun minusNotElem() { + val original = mapOf("A" to 1, "B" to 2) + val shortened = original - "C" + assertEquals(shortened["A"], 1) + assertEquals(shortened["B"], 2) + } + + test fun minusList() { + val original = mapOf("A" to 1, "B" to 2) + val shortened = original - listOf("B", "C") + assertEquals(shortened["A"], 1) + assertFalse(shortened.contains("B")) + assertFalse(shortened.contains("C")) + } + + test fun minusListNotElem() { + val original = mapOf("A" to 1, "B" to 2) + val shortened = original - listOf("C", "D") + assertEquals(shortened["A"], 1) + assertEquals(shortened["B"], 2) + } + + test fun minusSet() { + val original = mapOf("A" to 1, "B" to 2) + val shortened = original - setOf("B", "C") + assertEquals(shortened["A"], 1) + assertFalse(shortened.contains("B")) + assertFalse(shortened.contains("C")) + } + + test fun minusEmptySet() { + val original = mapOf("A" to 1, "B" to 2) + val shortened = original - setOf() + assertEquals(shortened["A"], 1) + assertEquals(shortened["B"], 2) + } + }