stdlib: Introduced filterIsInstance version

without class-literal as a parameter
This commit is contained in:
Denis Zharkov
2014-11-04 19:02:16 +04:00
committed by Andrey Breslav
parent da5164acd8
commit e768b4e285
5 changed files with 161 additions and 6 deletions
@@ -324,6 +324,27 @@ public fun ShortArray.fill(element: Short): ShortArray {
return this
}
/**
* Returns a list containing all elements that are instances of specified type parameter R
*/
public inline fun <reified R> Array<*>.filterIsInstance(): List<R> {
return filterIsInstanceTo(ArrayList<R>())
}
/**
* Returns a list containing all elements that are instances of specified type parameter R
*/
public inline fun <reified R> Iterable<*>.filterIsInstance(): List<R> {
return filterIsInstanceTo(ArrayList<R>())
}
/**
* Returns a stream containing all elements that are instances of specified type parameter R
*/
public inline fun <reified R> Stream<*>.filterIsInstance(): Stream<R> {
return FilteringStream(this, true, { it is R }) as Stream<R>
}
/**
* Returns a list containing all elements that are instances of specified class
*/
@@ -345,6 +366,30 @@ public fun <T, R : T> Stream<T>.filterIsInstance(klass: Class<R>): Stream<R> {
return FilteringStream(this, true, { klass.isInstance(it) }) as Stream<R>
}
/**
* Appends all elements that are instances of specified type parameter R to the given *destination*
*/
public inline fun <reified R, C : MutableCollection<in R>> Array<*>.filterIsInstanceTo(destination: C): C {
for (element in this) if (element is R) destination.add(element)
return destination
}
/**
* Appends all elements that are instances of specified type parameter R to the given *destination*
*/
public inline fun <reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceTo(destination: C): C {
for (element in this) if (element is R) destination.add(element)
return destination
}
/**
* Appends all elements that are instances of specified type parameter R to the given *destination*
*/
public inline fun <reified R, C : MutableCollection<in R>> Stream<*>.filterIsInstanceTo(destination: C): C {
for (element in this) if (element is R) destination.add(element)
return destination
}
/**
* Appends all elements that are instances of specified class to the given *destination*
*/
@@ -104,4 +104,42 @@ class CollectionJVMTest {
test fun takeReturnsFirstNElements() {
expect(setOf(1, 2)) { sortedSetOf(1, 2, 3, 4, 5).take(2).toSet() }
}
test fun filterIsInstanceList() {
val src: List<Any> = listOf(1,2,3.toDouble(), "abc", "cde")
val ints: List<Int> = src.filterIsInstance<Int>()
assertEquals(arrayListOf(1,2), ints)
val doubles: List<Double> = src.filterIsInstance<Double>()
assertEquals(arrayListOf(3.0), doubles)
val strings: List<String> = src.filterIsInstance<String>()
assertEquals(arrayListOf("abc", "cde"), strings)
val anys: List<Any> = src.filterIsInstance<Any>()
assertEquals(src.toList(), anys)
val chars: List<Char> = src.filterIsInstance<Char>()
assertEquals(0, chars.size())
}
test fun filterIsInstanceArray() {
val src: Array<Any> = array(1,2,3.toDouble(), "abc", "cde")
val ints: List<Int> = src.filterIsInstance<Int>()
assertEquals(arrayListOf(1,2), ints)
val doubles: List<Double> = src.filterIsInstance<Double>()
assertEquals(arrayListOf(3.0), doubles)
val strings: List<String> = src.filterIsInstance<String>()
assertEquals(arrayListOf("abc", "cde"), strings)
val anys: List<Any> = src.filterIsInstance<Any>()
assertEquals(src.toList(), anys)
val chars: List<Char> = src.filterIsInstance<Char>()
assertEquals(0, chars.size())
}
}
@@ -0,0 +1,26 @@
package test.collections
import org.junit.Test as test
import kotlin.test.assertEquals
class StreamJVMTest {
test fun filterIsInstance() {
val src: Stream<Any> = listOf(1,2,3.toDouble(), "abc", "cde").stream()
val ints: Stream<Int> = src.filterIsInstance<Int>()
assertEquals(arrayListOf(1,2), ints.toArrayList())
val doubles: Stream<Double> = src.filterIsInstance<Double>()
assertEquals(arrayListOf(3.0), doubles.toArrayList())
val strings: Stream<String> = src.filterIsInstance<String>()
assertEquals(arrayListOf("abc", "cde"), strings.toArrayList())
val anys: Stream<Any> = src.filterIsInstance<Any>()
assertEquals(src.toList(), anys.toArrayList())
val chars: Stream<Char> = src.filterIsInstance<Char>()
assertEquals(0, chars.toArrayList().size())
}
}
@@ -36,6 +36,7 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
var toNullableT: Boolean = false
var defaultInline = false
var receiverAsterisk = false
val inlineFamilies = HashMap<Family, Boolean>()
val buildFamilies = HashSet<Family>(defaultFamilies.toList())
@@ -104,6 +105,10 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
typeParams.add(t)
}
fun receiverAsterisk(v: Boolean) {
receiverAsterisk = true
}
fun inline(value: Boolean, vararg families: Family) {
if (families.isEmpty())
defaultInline = value
@@ -157,13 +162,14 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
if (returnType.isEmpty())
throw RuntimeException("No return type specified for $signature")
val isAsteriskOrT = if (receiverAsterisk) "*" else "T"
val receiver = when (f) {
Iterables -> "Iterable<T>"
Collections -> "Collection<T>"
Lists -> "List<T>"
Iterables -> "Iterable<$isAsteriskOrT>"
Collections -> "Collection<$isAsteriskOrT>"
Lists -> "List<$isAsteriskOrT>"
Maps -> "Map<K, V>"
Streams -> "Stream<T>"
ArraysOfObjects -> "Array<T>"
Streams -> "Stream<$isAsteriskOrT>"
ArraysOfObjects -> "Array<$isAsteriskOrT>"
Strings -> "String"
ArraysOfPrimitives -> primitive?.let { it.name() + "Array" } ?: throw IllegalArgumentException("Primitive array should specify primitive type")
else -> throw IllegalStateException("Invalid family")
@@ -215,7 +221,7 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
if (primitive == null && f != Strings) {
val implicitTypeParameters = receiver.dropWhile { it != '<' }.drop(1).filterNot { it == ' ' }.takeWhile { it != '>' }.split(",")
for (implicit in implicitTypeParameters.reverse()) {
if (!types.any { it.startsWith(implicit) }) {
if (implicit != "*" && !types.any { it.startsWith(implicit) || it.startsWith("reified " + implicit) }) {
types.add(0, implicit)
}
}
@@ -107,5 +107,45 @@ fun specialJVM(): List<GenericFunction> {
}
}
templates add f("filterIsInstanceTo(destination: C)") {
doc { "Appends all elements that are instances of specified type parameter R to the given *destination*" }
typeParam("reified R")
typeParam("C : MutableCollection<in R>")
inline(true)
receiverAsterisk(true)
returns("C")
exclude(ArraysOfPrimitives, Strings)
body {
"""
for (element in this) if (element is R) destination.add(element)
return destination
"""
}
}
templates add f("filterIsInstance()") {
doc { "Returns a list containing all elements that are instances of specified type parameter R" }
typeParam("reified R")
returns("List<R>")
inline(true)
receiverAsterisk(true)
body {
"""
return filterIsInstanceTo(ArrayList<R>())
"""
}
exclude(ArraysOfPrimitives, Strings)
doc(Streams) { "Returns a stream containing all elements that are instances of specified type parameter R" }
returns(Streams) { "Stream<R>" }
inline(true)
receiverAsterisk(true)
body(Streams) {
"""
return FilteringStream(this, true, { it is R }) as Stream<R>
"""
}
}
return templates
}