Simplify Kotlin Collections Creation with buildList, buildSet, and buildMap
This article explains how Kotlin's standard library provides concise builder functions such as buildList, buildSet, buildMap, and buildString to create immutable collections and strings efficiently, reducing boilerplate and eliminating lambda overhead while offering specialized variants for primitive types.
Preface
Many developers are unaware that Kotlin provides convenient functions for constructing collection classes such as List, Map, Set, and String.
Creating Lists
Typical mutable list creation uses mutableListOf or apply. Kotlin also offers the buildList { } function, which creates a mutable list internally, applies the lambda, and returns an immutable List. Because it is an inline function, the lambda overhead is eliminated.
val newList = mutableListOf<Int>()
newList.add(1)
if (conditionFullfilled) {
newList.add(2)
}
// OR using apply
val newList = mutableListOf<Int>().apply {
add(1)
if (conditionFullfilled) {
add(2)
}
}The buildList implementation delegates to buildListInternal and is annotated with @InlineOnly and contract to ensure exactly‑once invocation.
@SinceKotlin("1.6")
@WasExperimental(ExperimentalStdlibApi::class)
@kotlin.internal.InlineOnly
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
public inline fun <E> buildList(
@BuilderInference builderAction: MutableList<E>.() -> Unit
): List<E> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return buildListInternal(builderAction)
}Specialized builders such as buildIntList, buildLongList, buildFloatList, and buildDoubleList create primitive‑type lists without boxing. buildIntList { } → MutableIntList →
IntList buildLongList { }→ MutableLongList →
LongList buildFloatList { }→ MutableFloatList →
FloatList buildDoubleList { }→ MutableDoubleList →
DoubleListCreating Strings
Instead of manually using StringBuilder and append, the buildString { } function creates a StringBuilder, runs the lambda, and returns the final string, also as an inline function.
val sb = StringBuilder()
sb.append("Some")
if (conditionFullfilled) {
sb.append(" string")
}
val newString = sb.toString()
// OR using apply
val newString = StringBuilder().apply {
append("Some")
if (conditionFullfilled) {
append(" string")
}
}.toString() public inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return StringBuilder().apply(builderAction).toString()
}Creating Sets
Kotlin provides buildSet { } to construct a mutable set, apply actions, and return an immutable set preserving insertion order. Specialized versions exist for primitive types.
val newSet = buildSet {
add(1)
if (conditionFullfilled) {
addAll(someOtherSet)
}
} buildIntSet { }→ MutableIntSet →
IntSet buildFloatSet { }→ MutableFloatSet →
FloatSet buildLongSet { }→ MutableLongSet → LongSet These primitive‑type sets use flat hash tables and do not preserve insertion order.
Creating Maps
The buildMap { } function creates a mutable map, applies entries, and returns an immutable map. For maps with primitive keys/values, Kotlin offers optimized builders such as buildIntIntMap, buildLongLongMap, buildFloatFloatMap, and buildObjectObjectMap, as well as mixed‑type variants.
val newMap = buildMap {
put("key", "value")
if (conditionFullfilled) {
putAll(someOtherMap)
}
} buildIntIntMap { }→ MutableIntIntMap →
IntIntMap buildLongLongMap { }→ MutableLongLongMap →
LongLongMap buildFloatFloatMap { }→ MutableFloatFloatMap →
FloatFloatMap buildObjectObjectMap { }→ MutableObjectObjectMap → ObjectObjectMap Additional variants like buildIntFloatMap, buildIntLongMap, and buildObjectFloatMap cover other key/value type combinations.
Other Builders
Beyond the standard library, other libraries provide similar builders, e.g., buildSpannedString { } and buildAnnotatedString { } in Compose, and buildJsonObject in kotlinx‑serialization.
Conclusion
Kotlin’s standard library offers a set of concise builder functions for List, Map, Set, and String creation, standardizing construction patterns and eliminating repetitive boilerplate code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
AndroidPub
Senior Android Developer & Interviewer, regularly sharing original tech articles, learning resources, and practical interview guides. Welcome to follow and contribute!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
