skip to content

Compare buildSet with buildList: how do add semantics and iteration order differ, and what backing collection does buildSet use?

level: seniorimportance: nice to knowfreq 20%

answer

  1. buildSet.add dedups, returns false on duplicate
  2. buildList.add always appends
  3. Backing = LinkedHashSet -> insertion order
  4. Dedup via equals/hashCode
  5. buildSet vs buildList { }.distinct()

basics

~20 s

buildSet works like buildList but the temporary collection is a set, so adding a duplicate is ignored and add returns false. Like other Kotlin sets, it keeps elements in insertion order and returns a read-only Set.

solid answer

~30 s

buildSet exposes a `MutableSet<T>` receiver and returns `Set<T>`. Unlike `buildList`, where `add` always appends and allows duplicates, `buildSet`'s `add` deduplicates: adding an element already present is a no-op and returns `false` (vs `true` when newly inserted). The standard-library `buildSet` is backed by a `LinkedHashSet`, so iteration order is **insertion order**, matching `setOf`/`mutableSetOf` — not the unordered behavior of a plain `HashSet`. Equality/hashCode of `T` governs deduplication, so correct `equals`/`hashCode` (or being a data class) matters. `buildList` keeps insertion order too but permits and preserves duplicates. Both return read-only views over mutable backing collections.

code

kotlin · 5 lines
kotlin
val tags: Set<String> = buildSet {
    add("a")          // true
    add("a")          // false, ignored
    add("b")
} // [a, b] in insertion order

go deeper

for a junior

Knows buildSet drops duplicates and returns a read-only Set.

for a middle

Explains add's Boolean return and that order is insertion order, matching setOf.

for a senior

Identifies the LinkedHashSet backing, the equals/hashCode dependency for dedup, and contrasts the table of all three builders' add semantics.

for a principal

Chooses buildSet vs buildList.distinct() based on eager dedup, order guarantees, and equals/hashCode contracts in domain types, and considers performance of dedup during construction.

## Same shape, different element rules `buildSet { }` mirrors `buildList { }`: a receiver lambda whose `this` is the mutable collection, returning the read-only interface. The difference is **what `add` does**. ### buildList.add ```kotlin val l = buildList { add(1); add(1) } // [1, 1] -- duplicates kept ``` `MutableList.add` always appends and returns `true`. Order is insertion order; indices are stable. ### buildSet.add ```kotlin val s = buildSet { val first = add(1) // true (newly added) val dup = add(1) // false (already present, no-op) } // s == setOf(1) ``` `MutableSet.add` returns `Boolean`: `true` if the element was added, `false` if an equal element was already present. Duplicates are silently collapsed. ## Deduplication relies on equals/hashCode A set decides 'already present' via `hashCode()` then `equals()`. So: - Data classes work out of the box (structural equality). - Plain classes without overridden `equals`/`hashCode` dedup only by reference identity. ```kotlin data class P(val id: Int) val ps = buildSet { add(P(1)); add(P(1)) } // size 1 ``` ## Iteration order Kotlin's `buildSet` is backed by a **LinkedHashSet**, so iteration follows **insertion order** — the same predictable order you get from `setOf(...)` and `mutableSetOf(...)`. This is different from Java's bare `HashSet`, whose order is unspecified. So `buildSet` gives you dedup *and* deterministic order. ## What each returns and backs with | Builder | Receiver | Backing | Returns | add on duplicate | |--------|----------|---------|---------|------------------| | buildList | MutableList | ArrayList | List | appends (kept) | | buildSet | MutableSet | LinkedHashSet | Set | no-op, returns false | | buildMap | MutableMap | LinkedHashMap | Map | overwrites value | ## Practical use Reach for `buildSet` when you assemble a collection that must drop duplicates as you go (e.g., gathering distinct tags across items) while keeping a stable, insertion-ordered result — clearer than `buildList { }.distinct()` and it dedups eagerly during construction.

  • What does MutableSet.add return and when?
    Boolean: true when the element was newly added, false when an equal element was already present.
  • Why does iteration order from buildSet feel predictable?
    It's backed by a LinkedHashSet, which preserves insertion order, unlike a plain HashSet.

saying these in an interview costs you the question

  • Saying buildSet keeps duplicates like a list
  • Claiming buildSet has random/unspecified order (it's LinkedHashSet, insertion order)
  • Forgetting dedup depends on equals/hashCode
  • Thinking add always returns true for sets

context