Skip to main content

Grouping, association, and map lookup

Choose based on cardinality: can one key have one value, or many values?

OperationResult shapeDuplicate-key behavior
associateByMap<K, T>Later item replaces earlier item
groupByMap<K, List<T>>Every item is retained in a list
groupingByGrouping<T, K>Deferred grouping source for aggregation

One value versus many values​

data class Employee(val id: Int, val name: String, val department: String)

fun main() {
val employees = listOf(
Employee(1, "Rakesh", "Android"),
Employee(2, "Anu", "Backend"),
Employee(3, "Sam", "Android"),
)

val byId: Map<Int, Employee> = employees.associateBy { it.id }
val byDepartment: Map<String, List<Employee>> =
employees.groupBy { it.department }

println(byId[2]?.name) // Anu
println(byDepartment["Android"].orEmpty()) // Rakesh and Sam
}
Open in Kotlin Playground

Map lookup returns a nullable value because the key may be absent. orEmpty() is useful only when “missing group means empty group” is the intended domain rule.

Counting without constructing lists per key​

data class Employee(val name: String, val department: String)

fun main() {
val employees = listOf(
Employee("A", "Android"),
Employee("B", "Backend"),
Employee("C", "Android"),
)

val counts = employees
.groupingBy { it.department }
.eachCount()

println(counts) // {Android=2, Backend=1}
}
Open in Kotlin Playground

groupBy constructs Map<K, List<T>>. groupingBy creates a grouping abstraction consumed by operations such as eachCount, fold, or aggregate; it is useful when the final result is an aggregate rather than lists.

Duplicate IDs are a policy decision​

data class User(val id: Int, val name: String)

fun main() {
val users = listOf(User(1, "Old"), User(1, "New"))
val byId = users.associateBy { it.id }
println(byId) // {1=User(id=1, name=New)}
}
Open in Kotlin Playground

If duplicates violate the server or database contract, overwriting silently is dangerous. Detect them before choosing a winner:

val duplicates = users.groupBy { it.id }.filterValues { it.size > 1 }
require(duplicates.isEmpty()) { "Duplicate user IDs: ${duplicates.keys}" }
Open in Kotlin Playground

Interview questions​

  1. Why did an earlier value disappear after associateBy?
  2. What is the inferred type returned by groupBy?
  3. When is groupingBy().eachCount() preferable to groupBy()?
  4. Why does map[key] return V??