Compare `first()`, `firstOrNull()`, `find { }`, and `first { }` in Kotlin. What exceptions can they throw and how do they relate?
answer
- first() throws on empty; firstOrNull() → null
- find { } == firstOrNull { }
- predicate first { } throws if no match
- last/lastOrNull/findLast mirror the family
- all short-circuit at first match
basics
~20 sfirst() returns the first element but throws if the collection is empty. firstOrNull() returns null instead. first { predicate } returns the first matching element (throws if none); find { predicate } is the same but returns null if none match.
solid answer
~40 s`first()` returns element 0 and throws `NoSuchElementException` on an empty collection. `firstOrNull()` returns `T?`, giving `null` when empty. The predicate overloads search: `first { p }` returns the first element satisfying `p` and throws `NoSuchElementException` if none do; `firstOrNull { p }` returns `null` instead. `find { p }` is literally an alias for `firstOrNull { p }` — same behavior, more readable for searches. All stop at the first match (short-circuit), so they don't scan the whole collection. On a `List`, `first()` is O(1); the predicate variants are O(n) worst case. The mirror image is `last()` / `lastOrNull()` / `last { }` / `findLast { }` (alias of `lastOrNull { }`), which scan from the end (or whole list for predicate on iterables).
code
kotlin · 5 linesval users = listOf("amy", "bob", "cy")
users.first() // "amy"
users.find { it.startsWith("b") } // "bob"
users.firstOrNull { it.length > 9 } // null
val admin = users.find { it == "root" } ?: "guest" // "guest"go deeper
Knows first() throws and firstOrNull() is null-safe; can use find { } to search.
States that find == firstOrNull { }, that first { } throws on no match, and names the last-family mirror.
Discusses short-circuiting, O(1) head vs O(n) predicate, and Sequence laziness implications.
Codifies when absence is an error (throwing variant) vs expected (OrNull) and reviews APIs for consistent null handling.
## Plain first vs. predicate first - **`first()`** — returns the element at the start of iteration. On an **empty** collection it throws `NoSuchElementException` ("List is empty."). O(1) on `List`. - **`firstOrNull()`** — returns `T?`: the first element, or `null` if empty. Never throws. - **`first { predicate }`** — iterates and returns the **first element for which `predicate` returns true**; if no element matches it throws `NoSuchElementException` ("Collection contains no element matching the predicate."). It **short-circuits** — stops at the first hit. - **`firstOrNull { predicate }`** — same search, but returns `null` when nothing matches. - **`find { predicate }`** — defined as `public inline fun <T> Iterable<T>.find(predicate: (T) -> Boolean): T? = firstOrNull(predicate)`. It is an exact alias; choose `find` when the intent is "search for a match," and `firstOrNull` when the intent is "the head, if any." ```kotlin val nums = listOf(1, 2, 3, 4) nums.first() // 1 nums.firstOrNull() // 1 (null only if empty) nums.first { it > 2 } // 3 nums.find { it > 2 } // 3 (== firstOrNull { it > 2 }) nums.firstOrNull { it > 9 } // null // nums.first { it > 9 } // throws NoSuchElementException ``` ## The 'last' family mirrors it - `last()` / `lastOrNull()` — the final element (throws vs null on empty). - `last { p }` / `lastOrNull { p }` — last matching element. - `findLast { p }` is an alias of `lastOrNull { p }`. For a `List`, `last { p }` iterates backwards (efficient); for a general `Iterable` it must scan the whole sequence to find the last match. ## Choosing well - Use **OrNull** variants at boundaries where emptiness/no-match is expected and handle with `?:`/`?.let`. - Use the **throwing** variants when absence is a programmer error you want to surface loudly. - Prefer `find` over `firstOrNull { }` purely for readability — they compile to the same thing. ## Sequences On a `Sequence`, these are terminal operations that consume only as many elements as needed thanks to short-circuiting — `seq.first { p }` won't evaluate the tail past the first match.
- Is find different from firstOrNull with a predicate?No — find { p } is defined as firstOrNull(p). It is a readability alias; pick whichever reads clearer.
- What does first { p } throw when nothing matches?NoSuchElementException with the message that the collection contains no element matching the predicate.
- On a large lazy Sequence, does first { p } evaluate every element?No. It short-circuits and stops as soon as the predicate matches, so the tail is never evaluated.
first { } is a bouncer who insists someone matching must exist (and throws a fit if not); find is the calm one who just shrugs and returns null.
saying these in an interview costs you the question
- Saying firstOrNull throws on empty
- Claiming first() returns null when empty
- Believing find throws when no element matches
- Thinking find scans the whole collection even after a match (it short-circuits)
- Not knowing the last/lastOrNull/findLast counterparts