Building immutable collection dynamically in Kotlin

When and Why to Use Kotlin Collection Builders If there's a requirement to dynamically construct a collection based on certain conditions, two main approaches are available in Kotlin: Using a mutable collection directly Employing a collection builder function (e.g., buildSet, buildList, buildMap) The collection builder approach still uses a mutable collection internally, but the benefit lies in its encapsulation. This leads to cleaner and more concise code, and the final result is an immutable collection. This post is short and clear although I have met so much mutable collection in projects that is nice to remain it. Mutable way It works but collction must be muttable and code is less fluent. fun mapToWorkTypes(externalTypes: List): Set { val workTypes: MutableSet = mutableSetOf() if (externalTypes.contains("#001")) workTypes.add(EMPLOYEE) if (externalTypes.contains("#002")) workTypes.add(CONTRACTOR) if (externalTypes.contains("#003")) workTypes.add(SEASONAL) if (externalTypes.contains("#004")) workTypes.add(INTERN) if (externalTypes.contains("#005")) workTypes.add(CONTRACTOR) if (workTypes.isEmpty()) workTypes.add(EMPLOYEE) return workTypes.toSet() } Immutable way The code below uses collection builder. Check documentations of collection builders buildSet, buildList, buildMap. fun mapToWorkTypes(externalTypes: List) = buildSet { if (externalTypes.contains("#001")) add(EMPLOYEE) if (externalTypes.contains("#002")) add(CONTRACTOR) if (externalTypes.contains("#003")) add(SEASONAL) if (externalTypes.contains("#004")) add(INTERN) if (externalTypes.contains("#005")) add(CONTRACTOR) ifEmpty { add(EMPLOYEE) } } Conclusion Using a mutable collection directly requires more boilerplate and an explicit conversion to an immutable form via .toSet(). It also increases the risk of logic errors, such as accidentally checking or modifying the wrong collection (workTypes vs. externalTypes). In contrast, collection builders provide a cleaner and more concise alternative: Less boilerplate Clearer logic Automatically return immutable collections Encourage encapsulated and expressive code Whenever possible, prefer collection builders for constructing collections based on dynamic conditions.

Apr 22, 2025 - 13:58
 0
Building immutable collection dynamically in Kotlin

When and Why to Use Kotlin Collection Builders

If there's a requirement to dynamically construct a collection based on certain conditions, two main approaches are available in Kotlin:

  1. Using a mutable collection directly
  2. Employing a collection builder function (e.g., buildSet, buildList, buildMap)

The collection builder approach still uses a mutable collection internally, but the benefit lies in its encapsulation. This leads to cleaner and more concise code, and the final result is an immutable collection.

This post is short and clear although I have met so much mutable collection in projects that is nice to remain it.

Mutable way

It works but collction must be muttable and code is less fluent.

fun mapToWorkTypes(externalTypes: List<String>): Set<WorkType> {
    val workTypes: MutableSet<WorkType> = mutableSetOf()
    if (externalTypes.contains("#001")) workTypes.add(EMPLOYEE)
    if (externalTypes.contains("#002")) workTypes.add(CONTRACTOR)
    if (externalTypes.contains("#003")) workTypes.add(SEASONAL)
    if (externalTypes.contains("#004")) workTypes.add(INTERN)
    if (externalTypes.contains("#005")) workTypes.add(CONTRACTOR)
    if (workTypes.isEmpty()) workTypes.add(EMPLOYEE)
    return workTypes.toSet()
}

Immutable way

The code below uses collection builder. Check documentations of collection builders buildSet, buildList, buildMap.

fun mapToWorkTypes(externalTypes: List<String>) =
    buildSet {
        if (externalTypes.contains("#001")) add(EMPLOYEE)
        if (externalTypes.contains("#002")) add(CONTRACTOR)
        if (externalTypes.contains("#003")) add(SEASONAL)
        if (externalTypes.contains("#004")) add(INTERN)
        if (externalTypes.contains("#005")) add(CONTRACTOR)
        ifEmpty { add(EMPLOYEE) }
    }  

Conclusion

Using a mutable collection directly requires more boilerplate and an explicit conversion to an immutable form via .toSet(). It also increases the risk of logic errors, such as accidentally checking or modifying the wrong collection (workTypes vs. externalTypes).
In contrast, collection builders provide a cleaner and more concise alternative:

  • Less boilerplate
  • Clearer logic
  • Automatically return immutable collections
  • Encourage encapsulated and expressive code

Whenever possible, prefer collection builders for constructing collections based on dynamic conditions.