Most hand-written loops already exist as one named standard-library call. Pick by the result you need:
| You want | Call | Returns |
|---|---|---|
| Keep or split by a test | filter, partition | List, Pair of lists |
| One element or null | firstOrNull, maxByOrNull | T? |
| A yes/no answer | any, all, none | Boolean |
| A number | count, sumOf, maxOf | Int, Double... |
| A lookup table | associateBy, groupBy | Map |
| Fixed-size pieces | chunked, windowed | List<List<T>> |
On the catalog, books.partition { it.inStock } gives five available books and one sold out, books.sumOf { it.pages } gives 1714, and books.map { it.id }.chunked(4) gives [[1, 2, 3, 4], [5, 6]]. Prefer the OrNull variant (firstOrNull, maxByOrNull) when the collection may be empty, since first and maxBy throw. Use count { } rather than filter { }.size, and any { } rather than filter { }.isNotEmpty(): neither builds a throwaway list, and any stops at the first match. Switch to a sequence (Sequences and Lazy Evaluation) only when a profiler shows a chain over large data is hot.