What are the exact semantics of `single()`, `singleOrNull()`, `single { }`, and `singleOrNull { }` in Kotlin? When would you choose single over first?
answer
- single = exactly one, else throw
- empty → NoSuchElementException; >1 → IllegalArgumentException
- singleOrNull → null for empty AND for >1
- single { } can't short-circuit (must verify uniqueness)
- use single to enforce a uniqueness invariant
basics
~20 ssingle() returns the only element and throws if the collection is empty OR has more than one. singleOrNull() returns null in both of those cases. The predicate versions do the same but for elements matching a condition.
solid answer
~40 s`single()` asserts the collection holds **exactly one** element: it returns that element, throws `NoSuchElementException` when empty, and throws `IllegalArgumentException` ("Collection has more than one element.") when there are two or more. `singleOrNull()` returns `T?` — `null` for both the empty and the multiple cases (it swallows the error rather than throwing). `single { p }` returns the unique element matching `p` and throws if zero or more-than-one match; `singleOrNull { p }` returns `null` in those cases. Unlike `first { }`, the predicate `single { }` **cannot short-circuit on the first match** — it must keep scanning to verify no second match exists. Choose `single` to encode and enforce a uniqueness invariant (e.g., 'exactly one admin'); choose `first` when you only want the head and extra elements are fine.
code
kotlin · 4 linesdata class User(val id: Int, val role: String)
val users = listOf(User(1, "admin"), User(2, "user"))
val admin = users.single { it.role == "admin" } // User(1, admin)
val maybeRoot = users.singleOrNull { it.role == "root" } // null (none match)go deeper
Knows single() means 'exactly one or error' and singleOrNull() returns null otherwise.
Names both exception types and their cases, and distinguishes single from first for uniqueness intent.
Explains the no-short-circuit cost and uses single { } to surface duplicate-key bugs.
Promotes single as an invariant-enforcing tool in domain code and weighs its scan cost on hot paths.
## Uniqueness, not just the head Where `first()` answers "give me the head," `single()` answers "there should be exactly one — give me it, and complain otherwise." - **`single()`** - empty → throws `NoSuchElementException` ("...is empty.") - exactly one → returns it - two or more → throws `IllegalArgumentException` ("...has more than one element.") - **`singleOrNull()`** — returns `T?`; returns `null` for **both** the empty and the >1 cases, the element only when there's exactly one. - **`single { predicate }`** — returns the unique matching element; throws `NoSuchElementException` if none match and `IllegalArgumentException` if more than one matches. - **`singleOrNull { predicate }`** — `null` when zero or more than one match. ```kotlin listOf(42).single() // 42 // listOf<Int>().single() // NoSuchElementException // listOf(1, 2).single() // IllegalArgumentException listOf(1, 2).singleOrNull() // null (more than one) listOf(1, 2, 3).single { it % 2 == 0 } // 2 // listOf(2, 4).single { it % 2 == 0 } // IllegalArgumentException (two match) listOf(2, 4).singleOrNull { it % 2 == 0 } // null ``` ## Performance note: no short-circuit `first { p }` returns the moment the predicate is satisfied. `single { p }` **must** continue scanning after the first match to ensure no second element matches, so it always inspects the relevant remainder. On large collections, prefer `first`/`firstOrNull` when uniqueness isn't required. ## When to reach for single - Enforcing a domain invariant ('there is exactly one default address'). - Lookups by a key you believe is unique; `single { it.id == id }` surfaces accidental duplicates loudly instead of silently picking one. - `singleOrNull` is handy when both 'none' and 'ambiguous' should be treated as 'no clear answer'. ## Contrast table - empty: `single()` throws; `first()` throws; `singleOrNull()`/`firstOrNull()` → null. - multiple: `single()` throws; `first()` returns head; `singleOrNull()` → null; `firstOrNull()` → head.
- Which exception types does single() throw, and for which cases?NoSuchElementException when the collection is empty; IllegalArgumentException when it has more than one element.
- Why can't single { } short-circuit like first { }?It must keep scanning past the first match to prove no second element also matches before it can return.
single() is a strict roll-call: exactly one name must answer; silence or a second voice is an error.
saying these in an interview costs you the question
- Saying single() just returns the first element
- Claiming single() throws the same exception for empty and >1 (they differ)
- Thinking singleOrNull returns the first element when there are several (it returns null)
- Believing single { } short-circuits at the first match
- Using single when duplicates are legitimately possible