# Kotlin List to Map Conversion: 5 Efficient Methods for Custom Objects

> Learn 5 efficient Kotlin list to map conversion methods for custom objects. Discover associate, associateBy, associateWith, and groupBy for O(n) performance and minimal allocations.

- Repository: [JetBrains/kotlin](https://github.com/jetbrains/kotlin)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Kotlin provides inline extension functions—`associate`, `associateBy`, `associateWith`, and `groupBy`—that convert lists to maps in O(n) time with minimal allocations by leveraging stdlib implementations in [`libraries/stdlib/common/src/generated/_Collections.kt`](https://github.com/JetBrains/kotlin/blob/main/libraries/stdlib/common/src/generated/_Collections.kt).**

When working with the [JetBrains/kotlin](https://github.com/JetBrains/kotlin) repository's standard library, developers frequently need to transform collections of custom objects into lookup maps for efficient access. The Kotlin stdlib offers specialized **kotlin list to map conversion** functions that eliminate boilerplate while maintaining optimal performance through inline compilation and direct use of `LinkedHashMap` implementations.

## Core Extension Functions for List-to-Map Conversion

The Kotlin standard library defines four primary approaches in [`_Collections.kt`](https://github.com/JetBrains/kotlin/blob/main/_Collections.kt) that handle different mapping scenarios. Each function is declared as `inline`, allowing the compiler to eliminate lambda overhead and generate tight loops specialized for your specific types.

### Using associate() for Custom Key-Value Pairs

The `associate()` function provides maximum flexibility by letting you return a `Pair` for each element, defining both key and value explicitly.

According to the source in [`libraries/stdlib/common/src/generated/_Collections.kt`](https://github.com/JetBrains/kotlin/blob/main/libraries/stdlib/common/src/generated/_Collections.kt), the signature is:

```kotlin
inline fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>): Map<K, V>

```

The implementation iterates once over the collection, invoking `transform` for each element and inserting results into a mutable `LinkedHashMap`. This preserves the original list order while running in linear time.

### Using associateBy() for Key Selection

When your custom object should become the map value and you only need to extract the key, **associateBy** avoids the overhead of creating intermediate `Pair` objects.

The single-selector variant defined in the stdlib:

```kotlin
inline fun <T, K> Iterable<T>.associateBy(keySelector: (T) -> K): Map<K, T>

```

For scenarios requiring both key extraction and value transformation, use the two-parameter overload:

```kotlin
inline fun <T, K, V> Iterable<T>.associateBy(
    keySelector: (T) -> K, 
    valueTransform: (T) -> V
): Map<K, V>

```

### Using associateWith() for Value Derivation

If your custom object serves as the natural key and you need to compute derived values, use `associateWith()`. This maintains the element as the key while applying a transformation to generate values:

```kotlin
inline fun <T, V> Iterable<T>.associateWith(valueTransform: (T) -> V): Map<T, V>

```

### Using groupBy() for Multi-Value Grouping

Unlike the other functions that store single values, `groupBy` collects all elements sharing the same key into `List` values, making it ideal for grouping operations:

```kotlin
inline fun <T, K> Iterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>>

```

This allocates both the outer `LinkedHashMap` and inner `MutableList` instances for each unique key.

## Implementation Details and Performance Characteristics

All **kotlin list to map conversion** functions in the JetBrains repository share common implementation traits that optimize execution speed and memory usage.

### Inline Compilation Benefits

Because these functions are marked `inline`, the Kotlin compiler emits the lambda body directly at the call site rather than invoking it as an anonymous class. This eliminates object allocation for the lambda itself and enables type specialization for primitive values, reducing boxing overhead.

### LinkedHashMap and Order Preservation

The underlying implementations use `LinkedHashMap` rather than `HashMap`, ensuring that iteration order matches the original list sequence. This deterministic behavior is crucial when working with ordered collections of custom objects.

### Source File Location

The actual implementations reside in **[`libraries/stdlib/common/src/generated/_Collections.kt`](https://github.com/JetBrains/kotlin/blob/main/libraries/stdlib/common/src/generated/_Collections.kt)**, which contains the generated inline code that the compiler expands during compilation. This file handles the collection-to-map transformation logic used across all Kotlin platforms.

## Complete Code Examples with Custom Objects

Consider a custom data class representing users in a system:

```kotlin
data class Person(val id: Int, val name: String, val age: Int)

val people = listOf(
    Person(1, "Alice", 30),
    Person(2, "Bob", 25),
    Person(3, "Charlie", 30)
)

```

### Converting with associate()

Create a map from ID to name using the flexible pair constructor:

```kotlin
val idToName: Map<Int, String> = people.associate { it.id to it.name }
// Result: {1=Alice, 2=Bob, 3=Charlie}

```

### Converting with associateBy()

Store the full object as the value using a single key selector:

```kotlin
val idToPerson: Map<Int, Person> = people.associateBy { it.id }

```

Or transform the value while selecting the key, handling duplicate keys (last wins) automatically:

```kotlin
val ageToName: Map<Int, String> = people.associateBy(
    keySelector = { it.age },
    valueTransform = { it.name }
)
// Result: {30=Charlie, 25=Bob} - Charlie overwrites Alice for key 30

```

### Converting with associateWith()

Use the Person object as the key with computed values:

```kotlin
val personToAge: Map<Person, Int> = people.associateWith { it.age }

```

### Converting with groupBy()

Group multiple persons by age, creating lists for duplicate keys:

```kotlin
val personsByAge: Map<Int, List<Person>> = people.groupBy { it.age }
// Result: {30=[Alice, Charlie], 25=[Bob]}

```

## Performance Optimization Tips

When performing **kotlin list to map conversion** on large datasets, consider these strategies from the JetBrains stdlib implementation:

1. **Prefer `associateBy` over `associate`** when you only need the original element as the value. The `associate` function constructs an intermediate `Pair` for each element, while `associateBy` writes directly to the map, reducing allocation pressure.

2. **Use mutable maps only when necessary**. If you need to add entries after conversion, call `.toMutableMap()` on the result rather than using mutable operations during the initial transformation. The initial conversion remains O(n), and you avoid premature optimization complexity.

3. **Avoid `groupBy` for presence checks**. If you only need to verify whether a key exists rather than collecting all values, use `associateBy` with a dummy constant value. The `groupBy` function allocates a `List` for every unique key, consuming significantly more memory than a simple map when you don't need the grouped collections.

## Summary

- The Kotlin stdlib provides `associate`, `associateBy`, `associateWith`, and `groupBy` as inline extension functions for **kotlin list to map conversion**, all defined in [`libraries/stdlib/common/src/generated/_Collections.kt`](https://github.com/JetBrains/kotlin/blob/main/libraries/stdlib/common/src/generated/_Collections.kt).
- These functions operate in O(n) linear time, using `LinkedHashMap` to preserve input order and minimize allocations.
- The `inline` modifier eliminates lambda overhead, allowing the compiler to generate optimized, type-specific code for custom objects.
- `associateBy` offers better performance than `associate` when you don't need custom value transformations, as it avoids intermediate `Pair` creation.
- For grouping scenarios, `groupBy` creates `List` values for each key, while the other functions store single values and overwrite duplicates (last-write-wins).

## Frequently Asked Questions

### What is the difference between `associate` and `associateBy` in Kotlin list to map conversion?

The `associate` function requires a lambda that returns a `Pair<K, V>` for each element, giving you explicit control over both key and value generation but creating temporary `Pair` objects during processing. In contrast, `associateBy` takes a `keySelector` lambda and uses the original element as the value automatically, eliminating `Pair` allocation overhead and providing better performance when you don't need to transform the value.

### How does Kotlin handle duplicate keys during list to map conversion?

All stdlib conversion functions use `Map.put()` semantics where duplicate keys are overwritten by subsequent entries, following a last-write-wins strategy. For `associate`, `associateBy`, and `associateWith`, the final element in the list determines the value for any duplicate key. Only `groupBy` preserves all elements by collecting them into a `List` mapped to each key.

### Which function provides the best performance for converting a large list to a map?

For maximum performance with custom objects, use `associateBy` with a single key selector when the original element serves as the value, or `associateWith` when the element serves as the key. Both avoid the intermediate `Pair` allocation required by `associate`. The inline nature of these functions ensures the compiler generates specialized loops without boxing overhead for primitive properties.

### Does Kotlin preserve list order when converting to a map?

Yes, all standard list-to-map conversion functions in [`libraries/stdlib/common/src/generated/_Collections.kt`](https://github.com/JetBrains/kotlin/blob/main/libraries/stdlib/common/src/generated/_Collections.kt) use `LinkedHashMap` as their underlying implementation, which maintains insertion order during iteration. This means the resulting map iterates in the same sequence as the original list, providing deterministic behavior essential for debugging and UI consistency.