From 0ee960da50707c36e737c17ef5773021a683b66a Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Wed, 8 Jul 2015 21:10:33 +0300 Subject: [PATCH] Change removeAll extension implementation to match the contract of member removeAll. Add retainAll for sequences. --- .../kotlin/collections/MutableCollections.kt | 23 ++++++---- .../test/collections/CollectionJVMTest.kt | 23 ++++++++++ .../collections/MutableCollectionsTest.kt | 42 ++++++++++++++----- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/libraries/stdlib/src/kotlin/collections/MutableCollections.kt b/libraries/stdlib/src/kotlin/collections/MutableCollections.kt index 1f3db47782b..9a243c1e70d 100644 --- a/libraries/stdlib/src/kotlin/collections/MutableCollections.kt +++ b/libraries/stdlib/src/kotlin/collections/MutableCollections.kt @@ -47,31 +47,31 @@ public fun MutableCollection.addAll(array: Array) { } /** - * Removes all elements of the given [iterable] from this [MutableCollection]. + * Removes all elements from this [MutableCollection] that are also contained in the given [iterable]. */ public fun MutableCollection.removeAll(iterable: Iterable) { when (iterable) { is Collection -> removeAll(iterable) - else -> for (item in iterable) remove(item) + else -> removeAll(iterable.toHashSet()) } } /** - * Removes all elements of the given [sequence] from this [MutableCollection]. + * Removes all elements from this [MutableCollection] that are also contained in the given [sequence]. */ public fun MutableCollection.removeAll(sequence: Sequence) { - for (item in sequence) remove(item) + removeAll(sequence.toHashSet()) } /** - * Removes all elements of the given [array] from this [MutableCollection]. + * Removes all elements from this [MutableCollection] that are also contained in the given [array]. */ public fun MutableCollection.removeAll(array: Array) { - for (item in array) remove(item) + removeAll(array.toHashSet()) } /** - * Retains only elements of the given [iterable] in this [MutableCollection]. + * Retains only elements of this [MutableCollection] that are contained in the given [iterable]. */ public fun MutableCollection.retainAll(iterable: Iterable) { when (iterable) { @@ -81,8 +81,15 @@ public fun MutableCollection.retainAll(iterable: Iterable) { } /** - * Retains only elements of the given [array] in this [MutableCollection]. + * Retains only elements of this [MutableCollection] that are contained in the given [array]. */ public fun MutableCollection.retainAll(array: Array) { retainAll(array.toHashSet()) } + +/** + * Retains only elements of this [MutableCollection] that are contained in the given [sequence]. + */ +public fun MutableCollection.retainAll(sequence: Sequence) { + retainAll(sequence.toHashSet()) +} diff --git a/libraries/stdlib/test/collections/CollectionJVMTest.kt b/libraries/stdlib/test/collections/CollectionJVMTest.kt index 2d7d658290d..acd154b6a14 100644 --- a/libraries/stdlib/test/collections/CollectionJVMTest.kt +++ b/libraries/stdlib/test/collections/CollectionJVMTest.kt @@ -12,6 +12,29 @@ import org.junit.Test as test class CollectionJVMTest { + private fun identitySetOf(vararg values: T): MutableSet { + val map = IdentityHashMap() + values.forEach { map.put(it, "") } + return map.keySet() + } + + private data class IdentityData(public val value: Int) + + test fun removeAllWithDifferentEquality() { + val data = listOf(IdentityData(1), IdentityData(1)) + val list = data.toArrayList() + list -= identitySetOf(data[0]) as Iterable + assertTrue(list.single() === data[1], "Identity contains should be used") + + val list2 = data.toArrayList() + list2 -= hashSetOf(data[0]) as Iterable + assertTrue(list2.isEmpty(), "Equality contains should be used") + + val set3: MutableSet = identitySetOf(*data.toTypedArray()) + set3 -= arrayOf(data[1]) + assertTrue(set3.isEmpty(), "Array doesn't have contains, equality contains is used instead") + } + test fun flatMap() { val data = listOf("", "foo", "bar", "x", "") val characters = data.flatMap { it.toCharList() } diff --git a/libraries/stdlib/test/collections/MutableCollectionsTest.kt b/libraries/stdlib/test/collections/MutableCollectionsTest.kt index aa2a1460e4d..bffe1255e3b 100644 --- a/libraries/stdlib/test/collections/MutableCollectionsTest.kt +++ b/libraries/stdlib/test/collections/MutableCollectionsTest.kt @@ -8,22 +8,44 @@ import org.junit.Test as test class MutableCollectionTest { - test fun fromIterable() { - val data: Iterable = listOf("foo", "bar") + // TODO: Use apply scope function - val collection = ArrayList() - collection.addAll(data) + test fun addAll() { + val data = listOf("foo", "bar") - assertEquals(data, collection) + fun assertAdd(f: MutableList.() -> Unit) = assertEquals(data, arrayListOf().let { it.f(); it }) + + assertAdd { addAll(data) } + assertAdd { addAll(data.toTypedArray()) } + assertAdd { addAll(data.toTypedArray().asIterable()) } + assertAdd { addAll(data.asSequence()) } } - test fun fromSequence() { - val list = listOf("foo", "bar") - val collection = ArrayList() + test fun removeAll() { + val content = arrayOf("foo", "bar", "bar") + val data = listOf("bar") + val expected = listOf("foo") - collection.addAll(list.asSequence()) + fun assertRemove(f: MutableList.() -> Unit) = assertEquals(expected, arrayListOf(*content).let { it.f(); it }) - assertEquals(list, collection) + assertRemove { removeAll(data) } + assertRemove { removeAll(data.toTypedArray()) } + assertRemove { removeAll(data.toTypedArray().asIterable()) } + assertRemove { removeAll(data.asSequence()) } + } + + + test fun retainAll() { + val content = arrayOf("foo", "bar", "bar") + val data = listOf("bar") + val expected = listOf("bar", "bar") + + fun assertRetain(f: MutableList.() -> Unit) = assertEquals(expected, arrayListOf(*content).let { it.f(); it }) + + assertRetain { retainAll(data) } + assertRetain { retainAll(data.toTypedArray()) } + assertRetain { retainAll(data.toTypedArray().asIterable()) } + assertRetain { retainAll(data.asSequence()) } } }