From d1a12aa2a7de5d1774bd78c82a9fc8e6c357a77a Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 9 Jul 2015 21:24:33 +0300 Subject: [PATCH] plus, plusAssign, minus, minusAssign for all possible parameter types for Maps. #KT-6594 Fixed --- .../stdlib/src/kotlin/collections/Maps.kt | 133 +++++++++++--- libraries/stdlib/test/collections/MapTest.kt | 170 ++++++++---------- 2 files changed, 184 insertions(+), 119 deletions(-) diff --git a/libraries/stdlib/src/kotlin/collections/Maps.kt b/libraries/stdlib/src/kotlin/collections/Maps.kt index 099b350a108..4e2fbee23a7 100644 --- a/libraries/stdlib/src/kotlin/collections/Maps.kt +++ b/libraries/stdlib/src/kotlin/collections/Maps.kt @@ -320,27 +320,6 @@ public inline fun Map.filterNot(predicate: (Map.Entry) -> Boo return filterNotTo(LinkedHashMap(), predicate) } -/** - * 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. */ @@ -398,6 +377,24 @@ public fun Map.plus(pairs: Iterable>): Map { return newMap } +/** + * Creates a new read-only map by replacing or adding entries to this map from a given array of key-value [pairs]. + */ +public fun Map.plus(pairs: Array>): 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 a given sequence of key-value [pairs]. + */ +public fun Map.plus(pairs: Sequence>): 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]. */ @@ -407,21 +404,101 @@ public fun Map.plus(map: Map): Map { return newMap } +/** + * 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 pairs from the given array of [pairs] in this mutable map. + */ +public fun MutableMap.plusAssign(pairs: Array>) { + putAll(*pairs) +} + +/** + * Appends or replaces all pairs from the given sequence of [pairs] in this mutable map. + */ +public fun MutableMap.plusAssign(pairs: Sequence>) { + putAll(pairs) +} + +/** + * Appends or replaces all entries from the given [map] in this mutable map. + */ +public fun MutableMap.plusAssign(map: Map) { + putAll(map) +} + /** * 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 } + val result = LinkedHashMap(this) + result.minusAssign(key) + return result } /** * 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) - } + val result = LinkedHashMap(this) + result.minusAssign(keys) return result -} \ No newline at end of file +} + +/** + * Creates a new read-only map by removing a array of [keys] from this map. + */ +public fun Map.minus(keys: Array): Map { + val result = LinkedHashMap(this) + result.minusAssign(keys) + return result +} + +/** + * Creates a new read-only map by removing a sequence of [keys] from this map. + */ +public fun Map.minus(keys: Sequence): Map { + val result = LinkedHashMap(this) + result.minusAssign(keys) + return result +} + +/** + * Removes the given [key] from this mutable map. + */ +public fun MutableMap.minusAssign(key: K) { + remove(key) +} + +/** + * Removes all the given [keys] from this mutable map. + */ +public fun MutableMap.minusAssign(keys: Iterable) { + for (key in keys) remove(key) +} + +/** + * Removes all the given [keys] from this mutable map. + */ +public fun MutableMap.minusAssign(keys: Array) { + for (key in keys) remove(key) +} + +/** + * Removes all the given [keys] from this mutable map. + */ +public fun MutableMap.minusAssign(keys: Sequence) { + for (key in keys) remove(key) +} diff --git a/libraries/stdlib/test/collections/MapTest.kt b/libraries/stdlib/test/collections/MapTest.kt index 2a2e1c72f90..6eeec4ed7e4 100644 --- a/libraries/stdlib/test/collections/MapTest.kt +++ b/libraries/stdlib/test/collections/MapTest.kt @@ -268,120 +268,108 @@ class MapTest { assertEquals(3, filteredByValue["b"]) } - test fun plusAssign() { - val extended = hashMapOf(Pair("b", 3)) - extended += ("c" to 2) - assertEquals(2, extended.size()) - assertEquals(2, extended["c"]) - assertEquals(3, extended["b"]) + fun testPlusAssign(doPlusAssign: (MutableMap) -> Unit) { + val map = hashMapOf("a" to 1, "b" to 2) + doPlusAssign(map) + assertEquals(3, map.size()) + assertEquals(1, map["a"]) + assertEquals(4, map["b"]) + assertEquals(3, map["c"]) } - test fun plusAssignList() { - val extended = hashMapOf(Pair("b", 3)) - extended += listOf("C" to 3, "D" to 4) + test fun plusAssign() = testPlusAssign { + it += "b" to 4 + it += "c" to 3 + } + + test fun plusAssignList() = testPlusAssign { it += listOf("c" to 3, "b" to 4) } + + test fun plusAssignArray() = testPlusAssign { it += arrayOf("c" to 3, "b" to 4) } + + test fun plusAssignSequence() = testPlusAssign { it += sequenceOf("c" to 3, "b" to 4) } + + test fun plusAssignMap() = testPlusAssign { it += mapOf("c" to 3, "b" to 4) } + + fun testPlus(doPlus: (Map) -> Map) { + val original = mapOf("A" to 1, "B" to 2) + val extended = doPlus(original) assertEquals(3, extended.size()) + assertEquals(1, extended["A"]) + assertEquals(4, extended["B"]) 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() = testPlus { it + ("C" to 3) + ("B" to 4) } - test fun plus() { + test fun plusList() = testPlus { it + listOf("C" to 3, "B" to 4) } + + test fun plusArray() = testPlus { it + arrayOf("C" to 3, "B" to 4) } + + test fun plusSequence() = testPlus { it + sequenceOf("C" to 3, "B" to 4) } + + test fun plusMap() = testPlus { it + mapOf("C" to 3, "B" to 4) } + + + fun testMinus(doMinus: (Map) -> Map) { 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) + val shortened = doMinus(original) + assertEquals("A" to 1, shortened.entrySet().single().toPair()) } - 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 minus() = testMinus { it - "B" - "C" } + + test fun minusList() = testMinus { it - listOf("B", "C") } + + test fun minusArray() = testMinus { it - arrayOf("B", "C") } + + test fun minusSequence() = testMinus { it - sequenceOf("B", "C") } + + test fun minusSet() = testMinus { it - setOf("B", "C") } + + + + fun testMinusAssign(doMinusAssign: (MutableMap) -> Unit) { + val original = hashMapOf("A" to 1, "B" to 2) + doMinusAssign(original) + assertEquals("A" to 1, original.entrySet().single().toPair()) } - 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 minusAssign() = testMinusAssign { + it -= "B" + it -= "C" } - test fun plusListOverload() { + test fun minusAssignList() = testMinusAssign { it -= listOf("B", "C") } + + test fun minusAssignArray() = testMinusAssign { it -= arrayOf("B", "C") } + + test fun minusAssignSequence() = testMinusAssign { it -= sequenceOf("B", "C") } + + + fun testIdempotent(operation: (Map) -> Map) { 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) + assertEquals(original, operation(original)) } - test fun plusEmptyList() { - val original = mapOf("A" to 1, "B" to 2) - val extended = original + listOf() - assertEquals(extended["A"], 1) - assertEquals(extended["B"], 2) + fun testIdempotentAssign(operation: (MutableMap) -> Unit) { + val original = hashMapOf("A" to 1, "B" to 2) + val result = HashMap(original) + operation(result) + assertEquals(original, result) } - 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 plusEmptyList() = testIdempotent { it + listOf() } + test fun minusEmptyList() = testIdempotent { it - listOf() } - 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 plusEmptySet() = testIdempotent { it + setOf() } + test fun minusEmptySet() = testIdempotent { it - setOf() } - 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 plusAssignEmptyList() = testIdempotentAssign { it += listOf() } + test fun minusAssignEmptyList() = testIdempotentAssign { it -= listOf() } - 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 plusAssignEmptySet() = testIdempotentAssign { it += setOf() } + test fun minusAssignEmptySet() = testIdempotentAssign { it -= setOf() } - 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) - } }