From 28b079219104cbc35d6304bb6033c2a6061a48f5 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Tue, 3 Apr 2012 09:20:11 +0100 Subject: [PATCH] initial psike of #KT-39 on collections (iterators required too), though hit #KT-1710 --- libraries/stdlib/src/kotlin/JLangIterables.kt | 21 ++--- libraries/stdlib/src/kotlin/JUtil.kt | 57 +++++++++++--- libraries/stdlib/test/CollectionTest.kt | 78 ++++++++++++------- 3 files changed, 107 insertions(+), 49 deletions(-) diff --git a/libraries/stdlib/src/kotlin/JLangIterables.kt b/libraries/stdlib/src/kotlin/JLangIterables.kt index a8c741f3fd9..bbd0e979971 100644 --- a/libraries/stdlib/src/kotlin/JLangIterables.kt +++ b/libraries/stdlib/src/kotlin/JLangIterables.kt @@ -177,22 +177,25 @@ public inline fun java.lang.Iterable.reverse() : List { } /** Copies all elements into the given collection */ -public inline fun > java.lang.Iterable.to(result: C) : C { +public inline fun > java.lang.Iterable.to(result: C) : C { for (element in this) result.add(element) return result } -/** Copies all elements into a [[LinkedList]] */ -public inline fun java.lang.Iterable.toLinkedList() : LinkedList = to(LinkedList()) +/** Copies all elements into a [[LinkedList]] if its not already a [[LinkedList]] */ +public inline fun java.lang.Iterable.toLinkedList() : LinkedList = if (this is LinkedList) this else to(LinkedList()) -/** Copies all elements into a [[List]] */ -public inline fun java.lang.Iterable.toList() : List = to(ArrayList()) +/** Copies all elements into a [[List]] if its not already a [[List]] */ +public inline fun java.lang.Iterable.toList() : List = if (this is List) this else to(ArrayList()) -/** Copies all elements into a [[Set]] */ -public inline fun java.lang.Iterable.toSet() : Set = to(HashSet()) +/** Copies all elements into a [[List]] if it is not already a [[Collection]] */ +public inline fun java.lang.Iterable.toCollection() : Collection = if (this is Collection) this else to(ArrayList()) -/** Copies all elements into a [[SortedSet]] */ -public inline fun java.lang.Iterable.toSortedSet() : SortedSet = to(TreeSet()) +/** Copies all elements into a [[Set]] if its not already a [[Set]] */ +public inline fun java.lang.Iterable.toSet() : Set = if (this is Set) this else to(HashSet()) + +/** Copies all elements into a [[SortedSet]] if its not already a [[SortedSet]] */ +public inline fun java.lang.Iterable.toSortedSet() : SortedSet = if (this is SortedSet) this else to(TreeSet()) /** TODO figure out necessary variance/generics ninja stuff... :) diff --git a/libraries/stdlib/src/kotlin/JUtil.kt b/libraries/stdlib/src/kotlin/JUtil.kt index 3367dc8edfa..a0514d4513f 100644 --- a/libraries/stdlib/src/kotlin/JUtil.kt +++ b/libraries/stdlib/src/kotlin/JUtil.kt @@ -39,12 +39,58 @@ public inline fun java.util.Collection.toArray() : Array { return answer as Array } -/** TODO these functions don't work when they generate the Array versions when they are in JavaIterables */ +/** Returns true if the collection is not empty */ +public inline fun java.util.Collection.notEmpty() : Boolean = !this.isEmpty() + +/** Returns the Collection if its not null otherwise it returns the empty list */ +public inline fun java.util.Collection?.orEmpty() : Collection + = if (this != null) this else Collections.EMPTY_LIST as Collection + + +/** TODO these functions don't work when they generate the Array versions when they are in JLIterables */ public inline fun > java.lang.Iterable.toSortedList() : List = toList().sort() public inline fun > java.lang.Iterable.toSortedList(comparator: java.util.Comparator) : List = toList().sort(comparator) +/** + * Creates a new [[List]] with the element added at the end + * + * @includeFunctionBody ../../test/CollectionTest.kt plus + */ +public inline fun java.util.Collection.plus(element: T): List { + val list = to(ArrayList()) + list.add(element) + return list +} + +/** + * Adds the element to this collection + * + * @includeFunctionBody ../../test/CollectionTest.kt plusAssign + */ +public inline fun > C.plusAssign(element: T): C { + add(element) + return this +} + +/** + * Creates a new [[List]] with the element added at the end + */ +/* +public inline fun java.util.Collection.plus(elements: java.lang.Iterable): List = toList().plusAssign(elements) +*/ + +/** + * Adds all the elements to this collection + */ +/* +public inline fun > C.plusAssign(elements: java.lang.Iterable): C { + addAll(elements.toCollection()) + return this +} +*/ + // List APIs @@ -98,12 +144,3 @@ val List.tail : T? val List.last : T? get() = this.tail - - -/** Returns true if the collection is not empty */ -public inline fun java.util.Collection.notEmpty() : Boolean = !this.isEmpty() - -/** Returns the Collection if its not null otherwise it returns the empty list */ -public inline fun java.util.Collection?.orEmpty() : Collection - = if (this != null) this else Collections.EMPTY_LIST as Collection - diff --git a/libraries/stdlib/test/CollectionTest.kt b/libraries/stdlib/test/CollectionTest.kt index 86d061e8b74..b2f3aea751a 100644 --- a/libraries/stdlib/test/CollectionTest.kt +++ b/libraries/stdlib/test/CollectionTest.kt @@ -4,11 +4,11 @@ import kotlin.test.* import java.util.* -import org.junit.Test +import org.junit.Test as test class CollectionTest { - Test fun all() { + test fun all() { val data = arrayList("foo", "bar") assertTrue { data.all{it.length == 3} @@ -18,7 +18,7 @@ class CollectionTest { } } - Test fun any() { + test fun any() { val data = arrayList("foo", "bar") assertTrue { data.any{it.startsWith("f")} @@ -29,20 +29,20 @@ class CollectionTest { } - Test fun appendString() { + test fun appendString() { val data = arrayList("foo", "bar") val buffer = StringBuilder() val text = data.appendString(buffer, "-", "{", "}") assertEquals("{foo-bar}", buffer.toString()) } - Test fun count() { + test fun count() { val data = arrayList("foo", "bar") assertEquals(1, data.count{it.startsWith("b")}) assertEquals(2, data.count{it.size == 3}) } - Test fun filter() { + test fun filter() { val data = arrayList("foo", "bar") val foo = data.filter{it.startsWith("f")} assertTrue { @@ -52,7 +52,7 @@ class CollectionTest { assertEquals(arrayList("foo"), foo) } - Test fun filterNot() { + test fun filterNot() { val data = arrayList("foo", "bar") val foo = data.filterNot{it.startsWith("b")} @@ -64,7 +64,7 @@ class CollectionTest { } // TODO would be nice to avoid the - Test fun filterIntoLinkedList() { + test fun filterIntoLinkedList() { val data = arrayList("foo", "bar") val foo = data.filterTo(linkedList()){it.startsWith("f")} @@ -80,7 +80,7 @@ class CollectionTest { } // TODO would be nice to avoid the - Test fun filterNotIntoLinkedList() { + test fun filterNotIntoLinkedList() { val data = arrayList("foo", "bar") val foo = data.filterNotTo(linkedList()){it.startsWith("f")} @@ -96,7 +96,7 @@ class CollectionTest { } // TODO would be nice to avoid the - Test fun filterNotNullIntoLinkedList() { + test fun filterNotNullIntoLinkedList() { val data = arrayList(null, "foo", null, "bar") val foo = data.filterNotNullTo(linkedList()) @@ -108,7 +108,7 @@ class CollectionTest { } } - Test fun filterNotNull() { + test fun filterNotNull() { val data = arrayList(null, "foo", null, "bar") val foo = data.filterNotNull() @@ -120,7 +120,7 @@ class CollectionTest { } } - Test fun filterIntoSet() { + test fun filterIntoSet() { val data = arrayList("foo", "bar") // TODO would be nice to avoid the val foo = data.filterTo(hashSet()){it.startsWith("f")} @@ -136,7 +136,7 @@ class CollectionTest { } } - Test fun filterIntoSortedSet() { + test fun filterIntoSortedSet() { val data = arrayList("foo", "bar") // TODO would be nice to avoid the val sorted = data.filterTo(sortedSet()){it.length == 3} @@ -147,7 +147,7 @@ class CollectionTest { } } - Test fun find() { + test fun find() { val data = arrayList("foo", "bar") val x = data.find{it.startsWith("x")} assertNull(x) @@ -160,7 +160,7 @@ class CollectionTest { assertEquals("foo", f) } - Test fun flatMap() { + test fun flatMap() { val data = arrayList("", "foo", "bar", "x", "") val characters = data.flatMap{ it.toCharList() } println("Got list of characters ${characters}") @@ -169,7 +169,7 @@ class CollectionTest { assertEquals("foobarx", text) } - Test fun forEach() { + test fun forEach() { val data = arrayList("foo", "bar") var count = 0 data.forEach{ count += it.length } @@ -186,7 +186,7 @@ class CollectionTest { // numbers.map{it.toString()}.fold(""){it + it2} numbers.map{it.toString()}.fold(""){(it, it2) -> it + it2} */ - Test fun fold() { + test fun fold() { // lets calculate the sum of some numbers expect(10) { val numbers = arrayList(1, 2, 3, 4) @@ -210,7 +210,7 @@ class CollectionTest { // numbers.map{it.toString()}.foldRight(""){it + it2} numbers.map{it.toString()}.foldRight(""){(it, it2) -> it + it2} */ - Test fun foldRight() { + test fun foldRight() { expect("4321") { val numbers = arrayList(1, 2, 3, 4) numbers.map{it.toString()}.foldRight(""){(it, it2) -> it + it2} @@ -221,7 +221,7 @@ class CollectionTest { TODO inference engine should not need this type info? val byLength = words.groupBy{it.length} */ - Test fun groupBy() { + test fun groupBy() { val words = arrayList("a", "ab", "abc", "def", "abcd") val byLength = words.groupBy{it.length} assertEquals(4, byLength.size()) @@ -232,7 +232,7 @@ class CollectionTest { } - Test fun makeString() { + test fun makeString() { val data = arrayList("foo", "bar") val text = data.makeString("-", "<", ">") assertEquals("", text) @@ -243,7 +243,7 @@ class CollectionTest { we should be able to remove the explicit type on the map function http://youtrack.jetbrains.net/issue/KT-1145 */ - Test fun map() { + test fun map() { val data = arrayList("foo", "bar") val lengths = data.map{ it.length } assertTrue { @@ -253,13 +253,31 @@ class CollectionTest { assertEquals(arrayList(3, 3), lengths) } - Test fun reverse() { + test fun plus() { + val list = arrayList("foo", "bar") + val list2 = list + "cheese" + assertEquals(arrayList("foo", "bar"), list) + assertEquals(arrayList("foo", "bar", "cheese"), list2) + } + + test fun plusAssign() { + var list = arrayList("foo", "bar") +/* + TODO should we have plus and plus assign work differently for collections? + see KT-1710 + + list += "cheese" + assertEquals(arrayList("foo", "bar", "cheese"), list) +*/ + } + + test fun reverse() { val data = arrayList("foo", "bar") val rev = data.reverse() assertEquals(arrayList("bar", "foo"), rev) } - Test fun sort() { + test fun sort() { val coll: List = arrayList("foo", "bar", "abc") // TODO fixme @@ -272,7 +290,7 @@ class CollectionTest { } } - Test fun toArray() { + test fun toArray() { val data = arrayList("foo", "bar") val arr = data.toArray() println("Got array ${arr}") @@ -283,14 +301,14 @@ class CollectionTest { } } - Test fun simpleCount() { + test fun simpleCount() { val data = arrayList("foo", "bar") assertEquals(2, data.count()) assertEquals(3, hashSet(12, 14, 15).count()) assertEquals(0, ArrayList().count()) } - Test fun last() { + test fun last() { val data = arrayList("foo", "bar") assertEquals("bar", data.last()) assertEquals(25, arrayList(15, 19, 20, 25).last()) @@ -300,13 +318,13 @@ class CollectionTest { // assertEquals(19, TreeSet(arrayList(90, 47, 19)).first()) - Test fun lastException() { + test fun lastException() { fails { arrayList().last() } fails { linkedList().last() } fails { hashSet().last() } } - Test fun subscript() { + test fun subscript() { val list = arrayList("foo", "bar") assertEquals("foo", list[0]) assertEquals("bar", list[1]) @@ -329,7 +347,7 @@ class CollectionTest { assertEquals(arrayList("new", "thing", "works"), list) } - Test fun indices() { + test fun indices() { val data = arrayList("foo", "bar") val indices = data.indices assertEquals(0, indices.start) @@ -338,7 +356,7 @@ class CollectionTest { assertFalse(indices.isReversed) } - Test fun contains() { + test fun contains() { val data = arrayList("foo", "bar") assertTrue(data.contains("foo")) assertTrue(data.contains("bar"))