Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin short circuit map{}.firstOrNull{}

Tags:

kotlin

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.

like image 746
Love Avatar asked Jan 13 '17 10:01

Love


People also ask

Is kotlin short circuiting?

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.

What is .MAP in Kotlin?

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.


1 Answers

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()
like image 165
Ingo Kegel Avatar answered Oct 05 '22 10:10

Ingo Kegel