Collection processing in Kotlin: Finding, counting, and checking conditions
If you need to get the first element of a collection, use the first
method. To get the last one, use the last
method. To find an element at a concrete index, use the get
function, which is also an operator and can be replaced with box brackets. You can also destructure a list into elements, starting at the first position.
fun main() {
val c = ('a'..'z').toList()
println(c.first()) // a
println(c.last()) // z
println(c.get(3)) // d
println(c[3]) // d
val (c1, c2, c3) = c
println(c1) // a
println(c2) // b
println(c3) // c
}
A problem arises when a collection is empty. In such a case, all the functions above throw an exception (NoSuchElementException
or IndexOutOfBoundsException
). To prevent this, use the variants of these functions with the "OrNull" suffix.
fun main() {
val c = listOf<Char>()
println(c.firstOrNull()) // null
println(c.lastOrNull()) // null
println(c.getOrNull(3)) // null
}
Out of a whole collection of elements, we often want to find a single one that fulfills a predicate. It might be a user with a certain id, or a configuration with a concrete name. The most basic method of finding an element in a collection is find
.
fun getUser(id: String): User? =
users.find { it.id == id }
fun findConfiguration(name: String): Configuration? =
configurations.find { it.name == name }
find
is just an alias for firstOrNull
. They both return the first element that fulfills the predicate, or null
if no such element is found.
fun main() {
val names = listOf("Cookie", "Figa")
println(names.find { it.first() == 'A' }) // null
println(names.firstOrNull { it.first() == 'A' }) // null
println(names.find { it.first() == 'C' }) // Cookie
println(names.firstOrNull { it.first() == 'C' }) // Cookie
println(listOf(1, 2, 6, 11).find { it in 2..10 }) // 2
}
If you prefer to start searching from the end, you can use findLast
or lastOrNull
.
fun main() {
val names = listOf("C1", "C2")
println(names.find { it.first() == 'C' }) // C1
println(names.firstOrNull { it.first() == 'C' }) // C1
println(names.findLast { it.first() == 'C' }) // C2
println(names.lastOrNull { it.first() == 'C' }) // C2
}
Counting the number of elements in a list is easy as we can always use the size
property. However, some collections that implement the Iterable
interface might require iterating over elements to count how many elements they have. The universal method of counting the number of elements in a collection is count
.
fun main() {
val range = (1..100 step 3)
println(range.count()) // 34
}
We can also add a predicate to count
in order to count the number of elements that satisfy this predicate. For instance, we could count the number of users with a premium account, or the number of students that qualify for an internship.
val premiumUsersCount = users
.count { it.hasPremium }
val qualifiedNum = students
.count { qualifiesForInternship(it) }
The count
method returns the number of elements for which the predicate returned true
.
fun main() {
val range = (1..100 step 3)
println(range.count { it % 5 == 0 }) // 7
}
To check if a condition is true for all, any, or none of the elements in a collection, we use respectively all
, any
and none
. They all return a Boolean
. Let's see some examples.
data class Person(
val name: String,
val age: Int,
val male: Boolean
)
fun main() {
val people = listOf(
Person("Alice", 31, false),
Person("Bob", 29, true),
Person("Carol", 31, true)
)
fun isAdult(p: Person) = p.age > 18
fun isChild(p: Person) = p.age < 18
fun isMale(p: Person) = p.male
fun isFemale(p: Person) = !p.male
// Is there an adult?
println(people.any(::isAdult)) // true
// Are they all adults?
println(people.all(::isAdult)) // true
// Is none of them an adult?
println(people.none(::isAdult)) // false
// Is there any child?
println(people.any(::isChild)) // false
// Are they all children?
println(people.all(::isChild)) // false
// Are none of them children?
println(people.none(::isChild)) // true
// Are there any males?
println(people.any { isMale(it) }) // true
// Are they all males?
println(people.all { isMale(it) }) // false
// Is none of them a male?
println(people.none { isMale(it) }) // false
// Are there any females?
println(people.any { isFemale(it) }) // true
// Are they all females?
println(people.all { isFemale(it) }) // false
// Is none of them a female?
println(people.none { isFemale(it) }) // false
}
Beware: Developers often confuse the methods for finding elements, like find
or last
, with methods for checking a condition on elements, like any
.
For empty collections, the predicate is never called. any
returns false
, while all
and none
return true
. These values come from the mathematical definitions of these functions1.
fun main() {
val emptyList = emptyList<String>()
println(emptyList.any { error("Ignored") }) // false
println(emptyList.all { error("Ignored") }) // true
println(emptyList.none { error("Ignored") }) // true
}

Marcin Moskala is a highly experienced developer and Kotlin instructor as the founder of Kt. Academy, an official JetBrains partner specializing in Kotlin training, Google Developers Expert, known for his significant contributions to the Kotlin community. Moskala is the author of several widely recognized books, including "Effective Kotlin," "Kotlin Coroutines," "Functional Kotlin," "Advanced Kotlin," "Kotlin Essentials," and "Android Development with Kotlin."
Beyond his literary achievements, Moskala is the author of the largest Medium publication dedicated to Kotlin. As a respected speaker, he has been invited to share his insights at numerous programming conferences, including events such as Droidcon and the prestigious Kotlin Conf, the premier conference dedicated to the Kotlin programming language.