I need to map a list and retrieve the first non null element, and I need the map operation to be short circuited like it should be in Java 8 streams API. Is there a ready way to do this in Kotlin, without Java 8 streams?
I created my own extension method to do this:
fun <T, R> Iterable<T>.firstNonNullMapping(transform: (T) -> R?): R? {
for (element in this) {
val result = transform(element)
if (result != null) {
return result
}
}
return null
}
A test proves that this works
val firstNonNullMapping = listOf(null, 'a', 'b')
.firstNonNullMapping {
assertNotEquals(it, 'b') // Mapping should be stopped before reaching 'b'
it
}
assertEquals(firstNonNullMapping, 'a')
IntelliJ, however, suggest that I replace my for loop with the much neater
return this
.map { transform(it) }
.firstOrNull { it != null }
Problem is that this will map all elements of the iterable, and it is essential to my use case that is stops at the first non null element.
Kotlin's && operator will short circuit (just like Java's) but only at runtime. What you are experiencing is a compile time error. The big difference to remember especially when comparing Kotlin (or Java) to Python is that Kotlin and Java are statically typed and have a compilation phase.
Kotlin map is a collection that contains pairs of objects. Map holds the data in the form of pairs which consists of a key and a value. Map keys are unique and the map holds only one value for each key. Kotlin distinguishes between immutable and mutable maps.
Kotlin has lazily evaluated sequences that correspond to Java 8 streams, instead of invoking stream()
on a collection, you invoke asSequence()
:
return this
.asSequence()
.mapNotNull { transform(it) }
.firstOrNull()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With