skip to content

What do the random() and shuffled() collection extensions do in Kotlin, and how can you control which generator they use?

level: middleimportance: should knowfreq 60%

answer

  1. random() one element, shuffled() new ordered list
  2. shuffle() (no d) mutates in place
  3. all have a Random overload for seeding
  4. random() throws on empty, randomOrNull() returns null
  5. Fisher–Yates under the hood

basics

~10 s

list.random() returns one random element; list.shuffled() returns a new list with the elements in random order. Both have overloads taking a Random instance so you can pass a seeded generator.

solid answer

~40 s

`Collection.random()` returns a single uniformly-chosen element; on an empty collection it throws `NoSuchElementException`. The null-safe variant `randomOrNull()` returns `null` instead. `Iterable.shuffled()` returns a brand-new `List` with elements in random order, leaving the source untouched (it is non-mutating). For a `MutableList` there is the in-place `shuffle()` (no 'd') that reorders the receiver and returns `Unit`. Each of these has an overload accepting a `Random` argument — `list.random(rng)`, `list.shuffled(rng)`, `mutableList.shuffle(rng)` — so passing a seeded `Random(seed)` makes the selection/order deterministic, which is the standard pattern for testing. `(1..100).random()` works too because ranges support the same extension. Internally shuffled uses a Fisher–Yates shuffle for uniform permutations.

code

kotlin · 5 lines
kotlin
import kotlin.random.Random

val cards = (1..52).toList()
val dealt = cards.shuffled(Random(7)).take(5) // reproducible 5-card hand
val winner = listOf("a", "b", "c").randomOrNull() // null-safe pick

go deeper

for a junior

Knows list.random() picks an element and list.shuffled() randomizes order.

for a middle

Distinguishes shuffled (copy) from shuffle (in place), uses randomOrNull, and seeds via the Random overload.

for a senior

Knows the Fisher–Yates uniformity guarantee and the empty-collection exception, and injects generators for testability.

for a principal

Standardizes generator injection across randomized code paths so behavior is testable and reproducible by policy.

## Random-selection extensions Kotlin's stdlib adds randomness helpers directly onto collections so you rarely touch indices by hand. ### Picking one element - `fun <T> Collection<T>.random(): T` — uniformly random element. **Throws `NoSuchElementException` on an empty collection.** - `fun <T> Collection<T>.randomOrNull(): T?` — returns `null` on empty instead of throwing. Prefer this when emptiness is possible. - Overloads `random(random: Random)` / `randomOrNull(random: Random)` accept an explicit generator. ```kotlin val colors = listOf("red", "green", "blue") val pick = colors.random() // uses Random.Default val seededPick = colors.random(Random(1)) // deterministic val safe = emptyList<String>().randomOrNull() // null, no throw ``` ### Reordering - `fun <T> Iterable<T>.shuffled(): List<T>` — returns a **new** list, leaving the original unchanged (non-mutating, returns a value). - `fun <T> MutableList<T>.shuffle()` — reorders the receiver **in place**, returns `Unit`. Note the missing 'd': `shuffle` mutates, `shuffled` returns a copy. - Both take an optional `Random` overload: `shuffled(rng)`, `shuffle(rng)`. ```kotlin val deck = (1..52).toList() val order = deck.shuffled() // new list, deck untouched val m = deck.toMutableList() m.shuffle(Random(42)) // m reordered in place, reproducible ``` ### Algorithm and uniformity `shuffled`/`shuffle` use the **Fisher–Yates** algorithm, which produces every permutation with equal probability when the generator is uniform. `random()` picks an index via `nextInt(size)`. ### Choosing the generator Every one of these defaults to `Random.Default` (unseeded). Passing a `Random` argument is how you inject reproducibility — the same seeded instance gives the same pick or the same shuffle every run, which is the idiomatic way to make tests over randomized logic deterministic. ### Gotchas - `shuffled` (value-returning) vs `shuffle` (in-place) is a common naming trap mirroring `sorted`/`sort` and `reversed`/`reverse`. - `random()` on a possibly-empty collection is a latent crash — reach for `randomOrNull()`.

  • What is the difference between shuffle() and shuffled()?
    shuffle() mutates a MutableList in place and returns Unit; shuffled() returns a new List and leaves the original untouched.
  • How do you make a list.random() call deterministic in a test?
    Pass a seeded generator: list.random(Random(seed)). The same seed picks the same element every run.

shuffled() is photocopying a deck and shuffling the copy; shuffle() is shuffling the deck you're holding.

saying these in an interview costs you the question

  • Saying shuffled() mutates the original list
  • Using random() on a collection that can be empty without handling NoSuchElementException
  • Claiming there is no way to seed these extensions
  • Confusing shuffle()'s return value (Unit) with a returned list

context