plus, plusAssign, minus, minusAssign for all possible parameter types for Maps.

#KT-6594 Fixed
This commit is contained in:
Ilya Gorbunov
2015-07-09 21:24:33 +03:00
parent e080753dc2
commit d1a12aa2a7
2 changed files with 184 additions and 119 deletions
+104 -27
View File
@@ -320,27 +320,6 @@ public inline fun <K, V> Map<K, V>.filterNot(predicate: (Map.Entry<K, V>) -> Boo
return filterNotTo(LinkedHashMap<K, V>(), predicate) return filterNotTo(LinkedHashMap<K, V>(), predicate)
} }
/**
* Appends or replaces the given [pair] in this mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(pair: Pair<K, V>) {
put(pair.first, pair.second)
}
/**
* Appends or replaces all pairs from the given collection of [pairs] in this mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(pairs: Iterable<Pair<K, V>>) {
putAll(pairs)
}
/**
* Appends or replaces all entries from the given [map] in this mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(map: Map<K, V>) {
putAll(map)
}
/** /**
* Returns a new map containing all key-value pairs from the given collection of pairs. * Returns a new map containing all key-value pairs from the given collection of pairs.
*/ */
@@ -398,6 +377,24 @@ public fun <K, V> Map<K, V>.plus(pairs: Iterable<Pair<K, V>>): Map<K, V> {
return newMap 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 <K, V> Map<K, V>.plus(pairs: Array<Pair<K, V>>): Map<K, V> {
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 <K, V> Map<K, V>.plus(pairs: Sequence<Pair<K, V>>): Map<K, V> {
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]. * Creates a new read-only map by replacing or adding entries to this map from another [map].
*/ */
@@ -407,21 +404,101 @@ public fun <K, V> Map<K, V>.plus(map: Map<K, V>): Map<K, V> {
return newMap return newMap
} }
/**
* Appends or replaces the given [pair] in this mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(pair: Pair<K, V>) {
put(pair.first, pair.second)
}
/**
* Appends or replaces all pairs from the given collection of [pairs] in this mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(pairs: Iterable<Pair<K, V>>) {
putAll(pairs)
}
/**
* Appends or replaces all pairs from the given array of [pairs] in this mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(pairs: Array<Pair<K, V>>) {
putAll(*pairs)
}
/**
* Appends or replaces all pairs from the given sequence of [pairs] in this mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(pairs: Sequence<Pair<K, V>>) {
putAll(pairs)
}
/**
* Appends or replaces all entries from the given [map] in this mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(map: Map<K, V>) {
putAll(map)
}
/** /**
* Creates a new read-only map by removing a [key] from this map. * Creates a new read-only map by removing a [key] from this map.
*/ */
public fun <K, V> Map<K, V>.minus(key: K): Map<K, V> { public fun <K, V> Map<K, V>.minus(key: K): Map<K, V> {
return this.filterKeys { key != it } val result = LinkedHashMap<K, V>(this)
result.minusAssign(key)
return result
} }
/** /**
* Creates a new read-only map by removing a collection of [keys] from this map. * Creates a new read-only map by removing a collection of [keys] from this map.
*/ */
public fun <K, V> Map<K, V>.minus(keys: Iterable<K>): Map<K, V> { public fun <K, V> Map<K, V>.minus(keys: Iterable<K>): Map<K, V> {
val result = LinkedHashMap<K, V>() val result = LinkedHashMap<K, V>(this)
result.putAll(this) result.minusAssign(keys)
for (entry in keys) {
result.remove(entry)
}
return result return result
} }
/**
* Creates a new read-only map by removing a array of [keys] from this map.
*/
public fun <K, V> Map<K, V>.minus(keys: Array<K>): Map<K, V> {
val result = LinkedHashMap<K, V>(this)
result.minusAssign(keys)
return result
}
/**
* Creates a new read-only map by removing a sequence of [keys] from this map.
*/
public fun <K, V> Map<K, V>.minus(keys: Sequence<K>): Map<K, V> {
val result = LinkedHashMap<K, V>(this)
result.minusAssign(keys)
return result
}
/**
* Removes the given [key] from this mutable map.
*/
public fun <K, V> MutableMap<K, V>.minusAssign(key: K) {
remove(key)
}
/**
* Removes all the given [keys] from this mutable map.
*/
public fun <K, V> MutableMap<K, V>.minusAssign(keys: Iterable<K>) {
for (key in keys) remove(key)
}
/**
* Removes all the given [keys] from this mutable map.
*/
public fun <K, V> MutableMap<K, V>.minusAssign(keys: Array<K>) {
for (key in keys) remove(key)
}
/**
* Removes all the given [keys] from this mutable map.
*/
public fun <K, V> MutableMap<K, V>.minusAssign(keys: Sequence<K>) {
for (key in keys) remove(key)
}
+79 -91
View File
@@ -268,120 +268,108 @@ class MapTest {
assertEquals(3, filteredByValue["b"]) assertEquals(3, filteredByValue["b"])
} }
test fun plusAssign() { fun testPlusAssign(doPlusAssign: (MutableMap<String, Int>) -> Unit) {
val extended = hashMapOf(Pair("b", 3)) val map = hashMapOf("a" to 1, "b" to 2)
extended += ("c" to 2) doPlusAssign(map)
assertEquals(2, extended.size()) assertEquals(3, map.size())
assertEquals(2, extended["c"]) assertEquals(1, map["a"])
assertEquals(3, extended["b"]) assertEquals(4, map["b"])
assertEquals(3, map["c"])
} }
test fun plusAssignList() { test fun plusAssign() = testPlusAssign {
val extended = hashMapOf(Pair("b", 3)) it += "b" to 4
extended += listOf("C" to 3, "D" 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<String, Int>) -> Map<String, Int>) {
val original = mapOf("A" to 1, "B" to 2)
val extended = doPlus(original)
assertEquals(3, extended.size()) assertEquals(3, extended.size())
assertEquals(1, extended["A"])
assertEquals(4, extended["B"])
assertEquals(3, extended["C"]) assertEquals(3, extended["C"])
assertEquals(4, extended["D"])
} }
test fun plusAssignMap() { test fun plus() = testPlus { it + ("C" to 3) + ("B" to 4) }
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() { 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<String, Int>) -> Map<String, Int>) {
val original = mapOf("A" to 1, "B" to 2) val original = mapOf("A" to 1, "B" to 2)
val extended = original + ("C" to 3) val shortened = doMinus(original)
assertEquals(extended["A"], 1) assertEquals("A" to 1, shortened.entrySet().single().toPair())
assertEquals(extended["B"], 2)
assertEquals(extended["C"], 3)
} }
test fun plusList() { test fun minus() = testMinus { it - "B" - "C" }
val original = mapOf("A" to 1, "B" to 2)
val extended = original + listOf("C" to 3, "D" to 4) test fun minusList() = testMinus { it - listOf("B", "C") }
assertEquals(extended["A"], 1)
assertEquals(extended["B"], 2) test fun minusArray() = testMinus { it - arrayOf("B", "C") }
assertEquals(extended["C"], 3)
assertEquals(extended["D"], 4) test fun minusSequence() = testMinus { it - sequenceOf("B", "C") }
test fun minusSet() = testMinus { it - setOf("B", "C") }
fun testMinusAssign(doMinusAssign: (MutableMap<String, Int>) -> Unit) {
val original = hashMapOf("A" to 1, "B" to 2)
doMinusAssign(original)
assertEquals("A" to 1, original.entrySet().single().toPair())
} }
test fun plusMap() { test fun minusAssign() = testMinusAssign {
val original = mapOf("A" to 1, "B" to 2) it -= "B"
val extended = original + mapOf("C" to 3, "D" to 4) it -= "C"
assertEquals(extended["A"], 1)
assertEquals(extended["B"], 2)
assertEquals(extended["C"], 3)
assertEquals(extended["D"], 4)
} }
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<String, Int>) -> Map<String, Int>) {
val original = mapOf("A" to 1, "B" to 2) val original = mapOf("A" to 1, "B" to 2)
val extended = original + listOf("B" to 3, "C" to 4) assertEquals(original, operation(original))
assertEquals(extended["A"], 1)
assertEquals(extended["B"], 3)
assertEquals(extended["C"], 4)
} }
test fun plusEmptyList() { fun testIdempotentAssign(operation: (MutableMap<String, Int>) -> Unit) {
val original = mapOf("A" to 1, "B" to 2) val original = hashMapOf("A" to 1, "B" to 2)
val extended = original + listOf() val result = HashMap(original)
assertEquals(extended["A"], 1) operation(result)
assertEquals(extended["B"], 2) 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() { test fun plusEmptyList() = testIdempotent { it + listOf() }
val original = mapOf("A" to 1, "B" to 2) test fun minusEmptyList() = testIdempotent { it - listOf() }
val shortened = original - "B"
assertEquals(shortened["A"], 1)
assertFalse(shortened.contains("B"))
}
test fun minusNotElem() { test fun plusEmptySet() = testIdempotent { it + setOf() }
val original = mapOf("A" to 1, "B" to 2) test fun minusEmptySet() = testIdempotent { it - setOf() }
val shortened = original - "C"
assertEquals(shortened["A"], 1)
assertEquals(shortened["B"], 2)
}
test fun minusList() { test fun plusAssignEmptyList() = testIdempotentAssign { it += listOf() }
val original = mapOf("A" to 1, "B" to 2) test fun minusAssignEmptyList() = testIdempotentAssign { it -= listOf() }
val shortened = original - listOf("B", "C")
assertEquals(shortened["A"], 1)
assertFalse(shortened.contains("B"))
assertFalse(shortened.contains("C"))
}
test fun minusListNotElem() { test fun plusAssignEmptySet() = testIdempotentAssign { it += setOf() }
val original = mapOf("A" to 1, "B" to 2) test fun minusAssignEmptySet() = testIdempotentAssign { it -= setOf() }
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)
}
} }