🚗 · Single-element access

4 min read · Updated on by

Read on for an introduction to the most important functions for single element access: find, first, last, indexOf, lastIndexOf, single, and their variants.

Single-element access

find


//sampleStart
inline fun <T> Iterable<T>.find(predicate: (T) -> Boolean): T?
//sampleEnd

The find function searches for the first element satisfying a predicate and returns it. If no such element is found, it returns null.

Example


//sampleStart
fun main() {
    val list = listOf(1, 2, 3, 4, 5)
    list.find { it > 3 }.also(::println) // 4
    list.find { it < 0 }.also(::println) // null
}
//sampleEnd

There is also the findLast variant, which returns the last element satisfying a predicate, or null.


//sampleStart
inline fun <T> Iterable<T>.findLast(predicate: (T) -> Boolean): T?
//sampleEnd

Example


//sampleStart
fun main() {
    val list = listOf(1, 2, 3, 4, 5)
    list.findLast { it > 3 }.also(::println) // 5
    list.findLast { it < 3 }.also(::println) // 2
}
//sampleEnd

first, last


//sampleStart
fun <T> List<T>.first(): T
fun <T> List<T>.last(): T
//sampleEnd

The first/last functions return, as you would expect, the first/last elements of a list. When the list is empty, they throw a NoSuchElementException.

Example


//sampleStart
fun main() {
    val list = listOf(1, 2, 3, 4, 5)
    list.first().also(::println) // 1
    list.last().also(::println) // 5
}
//sampleEnd

There are a couple of useful variants.

One variant accepts a predicate, and returns the first/last element satisfying that predicate, or throws NoSuchElementException if no such element is found.


//sampleStart
inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T
inline fun <T> Iterable<T>.last(predicate: (T) -> Boolean): T
//sampleEnd

Example:


//sampleStart
fun main() {
    val list = listOf(1, 2, 3, 4, 5)
    list.first { it % 2 == 0 }.also(::println) // 2
    list.last { it % 2 == 0 }.also(::println) // 4
}
//sampleEnd

The *OrNull variants return null instead of throwing when run on an empty list.


//sampleStart
fun <T> List<T>.firstOrNull(): T?
fun <T> List<T>.lastOrNull(): T?
inline fun <T> Iterable<T>.firstOrNull(predicate: (T) -> Boolean): T
inline fun <T> Iterable<T>.lastOrNull(predicate: (T) -> Boolean): T
//sampleEnd

Finally, firstNotNullOf and firstNotNullOfOrNull apply a transformation to each element, and return the first result which is not null. The former throws NoSuchElementException if no such element is found, while the latter returns null.


//sampleStart
inline fun <T, R : Any> Iterable<T>.firstNotNullOf(
    transform: (T) -> R?
): R
inline fun <T, R : Any> Iterable<T>.firstNotNullOfOrNull(
    transform: (T) -> R?
): R?
//sampleEnd

Example


//sampleStart
interface Entity {
    val id: Long
}

interface EntityRepository {
    fun retrieve(id: Long): Entity?
    fun firstExisting(ids: List<Long>): Entity? = ids.firstNotNullOfOrNull { 
        retrieve(it) 
    }
}
//sampleEnd
fun main() {
    val poem = """
        In the code's carnival, Kotlin's the delight,
        With extension functions, it takes flight.
        From loops to spins, a coding spree,
        In the world of development, it's the key!
    """.trimIndent()
    println(poem)
}

indexOf, lastIndexOf


//sampleStart
fun <T> Iterable<T>.indexOf(element: T): Int
fun <T> Iterable<T>.lastIndexOf(element: T): Int
//sampleEnd

Returns the index of the first/last occurrence of element, or -1 if no such element is found.


//sampleStart
fun main() {
    val list = listOf(1, 2, 3, 2, 5)
    list.indexOf(2).also(::println) // 1
    list.lastIndexOf(2).also(::println) // 3
}
//sampleEnd

The related indexOfFirst/indexOfLast methods accepts a predicate and return the index of the first/last element that satisfies it.


//sampleStart
inline fun <T> Iterable<T>.indexOfFirst(
    predicate: (T) -> Boolean
): Int
inline fun <T> Iterable<T>.indexOfLast(
    predicate: (T) -> Boolean
): Int
//sampleEnd

Example


//sampleStart
fun main() {
    val list = listOf(1, 2, 3, 4, 5)
    list.indexOfFirst { it % 2 == 0 }.also(::println) // 1
    list.indexOfLast { it % 2 == 0 }.also(::println) // 3
}
//sampleEnd

single


//sampleStart
fun <T> Iterable<T>.single(): T
//sampleEnd

An interesting function that returns the single element of a list if it only contains a single element, and throws otherwise.

Example


//sampleStart
fun main() {
    // listOf().single() // throws NoSuchElementException
    listOf(1).single().also(::println) // 1
    // listOf(1, 2).single() // throws IllegalArgumentException
}
//sampleEnd

There are a few variations:

One variation accepts a predicate, and returns the element satisfying it if there is precisely one, and throws otherwise.


//sampleStart
fun <T> Iterable<T>.single(predicate: (T) -> Boolean): T
//sampleEnd

Example


//sampleStart
fun main() {
    val list = listOf(1, 2, 3)
    // list.single { it > 3 } // throws NoSuchElementException
    list.single { it > 2 }.also(::println) // 3
    // list.single { it > 1 } // throws IllegalArgumentException
}
//sampleEnd

There are also *OrNull variants for both of the above, which return null instead of throwing.


//sampleStart
fun <T> Iterable<T>.singleOrNull(): T?
fun <T> Iterable<T>.singleOrNull(predicate: (T) -> Boolean): T?
//sampleEnd

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

The Kotlin Primer