skip to content

Describe `chunked`, including its two overloads, the size of the final chunk, and how it differs from `windowed`.

level: middleimportance: should knowfreq 50%

answer

  1. Non-overlapping fixed-size sub-lists; last may be shorter
  2. size <= 0 throws IllegalArgumentException
  3. transform overload: list is transient — copy with toList()
  4. chunked(n) == windowed(n, step=n, partialWindows=true)
  5. Lazy on Sequence, eager on Iterable

basics

~10 s

chunked breaks a collection into consecutive, non-overlapping pieces of a fixed size. The last piece may be smaller if items run out. A second form lets you transform each piece as it's made.

solid answer

~40 s

`chunked(size: Int): List<List<T>>` splits a collection into consecutive **non-overlapping** sub-lists of at most `size` elements; the **last** chunk may be smaller when the total isn't divisible by `size`. `size` must be positive or it throws `IllegalArgumentException`. The overload `chunked(size, transform: (List<T>) -> R): List<R>` applies a transform to each chunk; importantly the `List<T>` passed in is a **transient** view reused between calls, so don't store it — copy it (e.g. `toList()`) if you need to retain it. It differs from `windowed`: `chunked(n)` is exactly `windowed(size = n, step = n, partialWindows = true)` — windows slide with a configurable `step` and can overlap, whereas chunks are disjoint. Useful for batching (e.g. paging IDs into DB queries). Available on `Iterable` and `Sequence` (lazy on the latter).

code

kotlin · 6 lines
kotlin
val ids = (1..10).toList()
ids.chunked(4)            // [[1,2,3,4],[5,6,7,8],[9,10]]
ids.chunked(4) { it.size } // [4, 4, 2]

// batching pattern
ids.chunked(3).forEach { batch -> /* query DB for `batch` */ }

go deeper

for a junior

Knows chunked splits into fixed-size, non-overlapping pieces with a possibly-shorter last one.

for a middle

Knows both overloads, the positive-size requirement, and relates chunked to windowed(step=size).

for a senior

Warns about the transient list in the transform overload and reasons about laziness on Sequence for large data.

for a principal

Applies chunking to batching/back-pressure problems and weighs eager vs sequence-based chunking for memory and throughput.

## What `chunked` does `chunked` splits a collection into **consecutive, non-overlapping** sub-lists ("chunks") of a fixed maximum size. ## Overloads - `chunked(size: Int): List<List<T>>` - `chunked(size: Int, transform: (List<T>) -> R): List<R>` ```kotlin (1..7).toList().chunked(3) // [[1, 2, 3], [4, 5, 6], [7]] <-- last chunk is smaller (1..7).toList().chunked(3) { it.sum() } // [6, 15, 7] ``` ## Key rules - **Size**: every chunk has exactly `size` elements **except possibly the last**, which holds the remainder. There is no padding. - **Positive size required**: `size <= 0` throws `IllegalArgumentException`. - **Transient list in the transform overload**: the `List<T>` handed to `transform` is a reused, ephemeral buffer; if you need to keep it beyond the lambda call, make a copy with `toList()`. Returning `it` directly from the transform without copying is a bug. - Order is preserved; it's eager on `Iterable`, **lazy** on `Sequence`. ## `chunked` vs `windowed` `chunked(n)` is defined in terms of `windowed`: ```kotlin list.chunked(n) == list.windowed(size = n, step = n, partialWindows = true) ``` - `windowed(size, step, partialWindows)` produces **sliding** windows: with `step < size` they **overlap**; with `step = size` they're disjoint (i.e. chunks). - `partialWindows = true` lets a short trailing window/chunk through; `windowed`'s default `partialWindows = false` would drop it — `chunked` always keeps the remainder. ```kotlin (1..5).toList().windowed(3, 1) // overlapping: [[1,2,3],[2,3,4],[3,4,5]] (1..5).toList().windowed(3, 3, true) // == chunked(3): [[1,2,3],[4,5]] ``` ## Typical use Batching: split a large list of IDs into chunks to fit query limits, then run one query per chunk. > Note: deep `windowed` mechanics belong to the sibling 'Windowing, Chunking & Zipping' leaf; here the focus is chunk-based grouping and how it relates to windowed.

  • In `chunked(3) { it }`, what's the danger of returning `it` directly?
    The List passed to transform is a transient buffer reused across chunks; returning it without toList() means all results may reference the same (last) contents. Copy it.
  • How do you replicate chunked using windowed?
    windowed(size = n, step = n, partialWindows = true) — equal step and size make non-overlapping chunks, and partialWindows keeps the short final one.

saying these in an interview costs you the question

  • Saying chunks overlap (that's windowed with step < size)
  • Claiming chunked pads the last chunk to full size
  • Storing the transform's transient list without copying
  • Thinking size = 0 returns empty instead of throwing

context