Kotlin

How To Convert A List To Map In Kotlin

How To Convert A List To Map In Kotlin

Converting a list to map in Kotlin is one of those operations you’ll use constantly, yet picking the wrong function leads to silent bugs that are tricky to trace. The Kotlin standard library gives you five different ways to do it: associate, associateBy, associateWith, toMap, and groupBy.

Each one handles key-value pair creation differently. And each one treats duplicate keys in its own way.

This guide covers the syntax, performance trade-offs, and real behavior of every list to map function in Kotlin’s Collections API. You’ll also see how these approaches compare to Java’s Collectors.toMap(), when to use buildMap for conditional logic, and how to avoid the duplicate key problems that quietly drop data from your results.

What Is List to Map Conversion in Kotlin

maxresdefault How To Convert A List To Map In Kotlin

List to map conversion in Kotlin is the process of transforming an ordered collection of elements into a set of key-value pairs. You take a List, which holds items by index, and produce a Map, which holds items by a unique key you define.

Why would you bother? Because lookup speed changes drastically.

Finding a specific element in a list requires scanning through items one by one. That’s O(n) time. A HashMap gives you O(1) lookups. For a list of 10 items, nobody cares. For 10,000 user records pulled from an API response, it matters a lot.

Google reports that 70% of the top 1,000 apps on the Play Store are written in Kotlin. JetBrains puts that number even higher, claiming 95% of those apps include some Kotlin code. This growing ecosystem is one reason companies increasingly look for Kotlin developers for hire who can build scalable Android, backend, and multiplatform applications efficiently.

Collection operations like list-to-map conversion show up constantly in these codebases.

The Kotlin standard library gives you several built-in functions for this:

  • associate returns a map where you define both the key and value from each element
  • associateBy lets you pick a key selector while keeping the original element as the value
  • associateWith uses each list element as a key and you supply the value
  • toMap converts an existing list of Pair objects directly
  • groupBy collects multiple elements under the same key into a list

Each one solves a slightly different problem. Picking the wrong one leads to silent bugs, especially around duplicate keys. Took me a while to internalize which function to reach for first, and honestly, associateBy covers about 80% of real-world cases.

Why is Kotlin becoming the new Java?

Discover Kotlin statistics: Android adoption, multiplatform growth, developer satisfaction, and the modern language evolution from JetBrains.

Explore Kotlin Data →

The Kotlin Collections API backs all of these with LinkedHashMap by default. That means insertion order is preserved in the resulting map, which catches some people off guard when they expect unordered behavior like a plain HashMap.

How associate Works for List to Map Conversion

maxresdefault How To Convert A List To Map In Kotlin

The associate function is the most flexible way to convert a list into a map. You give it a lambda that receives each element and returns a Pair<K, V>. The first item in the pair becomes the key, the second becomes the value.

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

val users = listOf( User(1, “Alice”, “alice@dev.io”), User(2, “Bob”, “bob@dev.io”), User(3, “Carol”, “carol@dev.io”) )

val emailById: Map<Int, String> = users.associate { it.id to it.email } // {1=alice@dev.io, 2=bob@dev.io, 3=carol@dev.io} `

The to infix function creates the Pair. You could write Pair(it.id, it.email) instead, but nobody does that in practice. The infix syntax reads better and it's what you'll see in every Kotlin codebase that touches collection transformations.

One thing to know: associate creates short-lived Pair objects internally. The official Kotlin documentation notes this directly, stating that associate() should be used when performance is not the top concern. For most software development scenarios, the overhead is negligible. But if you're running this inside a tight loop on a large dataset (100K+ items), consider associateBy instead.

Using the to Infix Function Inside associate

Readability difference:

` // Idiomatic Kotlin users.associate { it.id to it.name }

// Verbose alternative users.associate { Pair(it.id, it.name) } `

Looking to sharpen your Kotlin skills? Data classes, extension functions, null safety, and everything else you need - including let, apply, and scope functions - is on one page in the Kotlin Cheat Sheet.

Both produce identical results. The to infix function is a standard library extension that returns a Pair, and it's one of those small Kotlin features that makes lambda expressions feel clean rather than cluttered.

When the key and value come from different transformations of the same element, associate is the right pick. If you only need to specify the key, reach for associateBy instead.

Duplicate Key Behavior in associate

If two elements produce the same key, the last one wins. No warning, no exception.

` val items = listOf("apple", "apricot", "banana") val map = items.associate { it.first() to it } // {a=apricot, b=banana} -- "apple" is gone `

This silent overwrite is by design. The Kotlin team chose this approach for performance reasons. Checking for duplicate keys on every insertion would require double lookups in the map. Java’s Collectors.toMap() throws an IllegalStateException on duplicates by default, which is the opposite behavior.

How associateBy Maps List Elements by a Key Selector

maxresdefault How To Convert A List To Map In Kotlin

associateBy is what you want when each list element should become the value, and you just need to pick which property serves as the key.

` data class Product(val sku: String, val name: String, val price: Double)

val products = listOf( Product(“A100”, “Widget”, 9.99), Product(“B200”, “Gadget”, 24.50), Product(“C300”, “Thingamajig”, 4.75) )

val bySku: Map<String, Product> = products.associateBy { it.sku } // {“A100″=Product(…), “B200″=Product(…), “C300″=Product(…)} `

The JetBrains Developer Ecosystem Survey 2024 shows that 75% of Kotlin users express satisfaction with the language. Part of that probably comes from functions like associateBy that cut boilerplate compared to what you'd write in Java.

No intermediate Pair objects are created here. The function takes a key selector lambda and directly inserts each element into a LinkedHashMap. That's one less allocation per element versus associate.

associateBy With a Value Transform

There’s an overloaded version that accepts both a key selector and a value transform:

` val namesBySku: Map<String, String> = products.associateBy( keySelector = { it.sku }, valueTransform = { it.name } ) // {"A100"="Widget", "B200"="Gadget", "C300"="Thingamajig"} `

This version sits between associateBy (key only) and associate (full Pair control). It avoids Pair allocation while still letting you shape both sides of the map entry.

Your mileage may vary on when to use each one. But in my experience, the single-parameter associateBy covers most data class indexing scenarios. The overloaded version comes in handy when you need a flattened lookup table, like mapping user IDs to just their display names.

How associate With Maps List Elements as Keys

maxresdefault How To Convert A List To Map In Kotlin

With associateWith, the list elements themselves become the map keys. You provide a lambda that produces the value for each key.

This flips the direction compared to associateBy.

FunctionList Element BecomesLambda Produces
associateByValueKey
associateWithKeyValue
associateNeither (both from lambda)Key + Value pair

` val words = listOf("hello", "world", "kotlin") val lengthMap: Map<String, Int> = words.associateWith { it.length } // {hello=5, world=5, kotlin=6} `

Practical use cases include mapping strings to their lengths, objects to computed scores, or configuration keys to resolved values.

Netflix, Uber, and Pinterest all use Kotlin in production. When you’re processing lists of feature flags, permission strings, or API endpoint paths, associateWith is the cleanest way to attach metadata to each item without restructuring anything.

Same duplicate key rule applies. If two elements in the list are equal (by equals()), the last one's value wins. For a list of unique items, which is the common case, this never comes up.

Converting a List of Pairs to a Map With toMap

maxresdefault How To Convert A List To Map In Kotlin

Sometimes your data already exists as Pair objects before you need a map. Maybe you built them earlier in a processing chain, or you’re working with a function that returns pairs.

toMap() handles this directly:

` val entries = listOf("host" to "localhost", "port" to "8080", "env" to "dev") val config: Map<String, String> = entries.toMap() // {host=localhost, port=8080, env=dev} `

This is also what mapOf() uses under the hood. When you write mapOf(“a” to 1, “b” to 2), Kotlin creates a list of pairs and converts it. So toMap() on an existing list of pairs is doing the same thing, just explicitly.

When toMap Makes Sense

Processing chains: You’ve already zipped two lists or used map to produce pairs, and now you need a map at the end.

` val keys = listOf("name", "role", "team") val values = listOf("Alice", "Engineer", "Platform")

val result = keys.zip(values).toMap() // {name=Alice, role=Engineer, team=Platform} `

Destructured data: You’re reading key-value lines from a config file or a RESTful API response and splitting them into pairs first.

Duplicate key behavior is identical to associate. Last value wins, no exceptions thrown. If your pairs might contain duplicate keys and you need all values, skip toMap() and use groupBy instead.

Grouping List Elements Into a Map With groupBy

Every function covered so far drops duplicate keys silently. groupBy does the opposite. It collects all elements that share the same key into a list.

The return type tells the story: Map<K, List> instead of Map.

` data class Order(val product: String, val category: String, val amount: Double)

val orders = listOf( Order(“Laptop”, “Electronics”, 999.0), Order(“Phone”, “Electronics”, 699.0), Order(“Desk”, “Furniture”, 350.0), Order(“Chair”, “Furniture”, 200.0), Order(“Monitor”, “Electronics”, 450.0) )

val byCategory: Map<String, List<Order>> = orders.groupBy { it.category } // Electronics -> [Laptop, Phone, Monitor] // Furniture -> [Desk, Chair] `

Stack Overflow’s 2024 survey ranked Kotlin as the 4th most admired programming language with 58.2% developer satisfaction. Functions like groupBy are a big part of why. In Java, you'd need Collectors.groupingBy() with a stream pipeline. In Kotlin, it's one line.

Chaining groupBy With mapValues

Raw grouping is rarely the final step. You usually want to aggregate the grouped data.

` val totalByCategory = orders .groupBy { it.category } .mapValues { (, orders) -> orders.sumOf { it.amount } } // {Electronics=2148.0, Furniture=550.0} `

Common transformations after groupBy:

  • mapValues { it.value.size } for counting items per group
  • mapValues { it.value.maxByOrNull { item -> item.amount } } for the highest-value item per group
  • mapValues { it.value.map { item -> item.product } } for extracting just one property from each group

This pattern shows up in Android development all the time. Grouping notifications by type, organizing chat messages by date, bucketing search results by relevance tier. If you’re building any kind of mobile application, you’ll reach for groupBy more often than you'd expect.

groupBy vs associateBy for Duplicate Keys

This trips people up constantly.

ScenarioUse ThisWhy
Keys are guaranteed unique (IDs, SKUs)associateByOne value per key, direct lookup
Multiple elements share the same keygroupByCollects all values, nothing dropped
Unsure about duplicates but want safetygroupByPreserves everything, process later

If you use associateBy on a list with duplicate keys, some data vanishes without any error. I've seen this cause real bugs in production, especially when upstream data changes and suddenly introduces duplicates that didn't exist during initial testing. When in doubt, groupBy first. You can always flatten it later.

Handling Duplicate Keys During List to Map Conversion

maxresdefault How To Convert A List To Map In Kotlin

Duplicate keys are the single biggest source of bugs in list-to-map conversions. Most Kotlin collection functions handle them silently, which makes the problem harder to catch.

The Kotlin team chose “last value wins” as the default behavior for performance reasons. Checking for duplicates on every insertion would require double lookups into the HashMap, and the standard library prioritizes speed over safety here.

How Each Function Handles Duplicates

FunctionDuplicate BehaviorReturn Type
associateLast value silently winsMap
associateByLast value silently winsMap
associateWithLast value silently winsMap
groupByCollects all valuesMap<K, List>

Java’s Collectors.toMap() throws an IllegalStateException on duplicate keys by default. Kotlin does the opposite. Neither approach is wrong, but you need to know which one you're working with.

Custom Conflict Resolution With groupBy and mapValues

When you need control over how duplicates merge, chain groupBy with mapValues:

` data class Sale(val product: String, val revenue: Double)

val sales = listOf( Sale(“Widget”, 100.0), Sale(“Widget”, 250.0), Sale(“Gadget”, 75.0) )

// Keep first value only val firstSale = sales.groupBy { it.product } .mapValues { (, v) -> v.first() }

// Sum all values val totalRevenue = sales.groupBy { it.product } .mapValues { (_, v) -> v.sumOf { it.revenue } } // {Widget=350.0, Gadget=75.0} `

Common resolution strategies:

  • Keep first: .mapValues { it.value.first() }
  • Keep max: .mapValues { it.value.maxBy { v -> v.revenue } }
  • Merge values: .mapValues { it.value.sumOf { v -> v.revenue } }

Forbes reportedly shares over 80% of its business logic across iOS and Android using Kotlin Multiplatform. At that scale, a silent duplicate key bug in a shared data layer could affect both platforms simultaneously. Defensive coding with groupBy prevents that.

Performance Differences Between List to Map Functions in Kotlin

maxresdefault How To Convert A List To Map In Kotlin

All standard list-to-map functions in Kotlin run in O(n) time. You iterate once, you insert once per element. The differences show up in memory allocation, not algorithmic complexity.

Pair Allocation Overhead in associate

The Kotlin documentation states directly that associate() produces short-lived Pair objects. Each call to the to infix function creates a Pair instance on the heap before the key-value entry lands in the map.

associateBy skips this entirely. It takes a key selector and inserts the element directly into the LinkedHashMap.

Baeldung’s JMH benchmarks show Kotlin’s inline functions are about 44% more efficient than equivalent Java lambda calls. The associate family benefits from this since they're all declared as inline in the standard library, meaning the lambda body gets compiled directly into the call site.

When to Use buildMap Instead

Conditional logic: buildMap (available since Kotlin 1.6) gives you a MutableMap receiver inside a builder lambda. You can add entries conditionally, skip some, or merge values manually.

` val config = buildMap { put("host", "localhost") if (isProduction) put("port", "443") else put("port", "8080") putAll(overrides) } `

Pre-sizing: The overloaded buildMap(capacity) lets you hint the expected size. Pre-sizing a HashMap avoids internal resizing. One analysis on Medium found this produces 10-20% faster results for large datasets.

For standard one-to-one conversions, stick with associateBy. Reach for buildMap when you need if statements, merging, or any logic that doesn't fit into a single lambda expression.

Sequences vs Collections for Large Lists

A 2025 benchmark by Chris Banes found that for simple chained operations, using a Kotlin Sequence was actually about 9% slower than the standard collection approach. Sequences avoid intermediate collections, but the overhead of the lazy evaluation pipeline costs more than it saves for short chains.

For a single associate or associateBy call on a list, sequences add nothing. The conversion is one pass with no intermediate collections anyway. Sequences only start paying off when you chain multiple transformations (filter, map, associate) on very large datasets.

List to Map With Index Using mapIndexed and withIndex

Sometimes the list index itself needs to be part of the map. Maybe you’re numbering items, building a position lookup, or tagging elements with their original order after a sort.

Using withIndex and associate

` val colors = listOf("red", "green", "blue")

val indexToColor = colors.withIndex() .associate { (index, value) -> index to value } // {0=red, 1=green, 2=blue} `

withIndex() wraps each element in an IndexedValue object. The destructuring syntax (index, value) pulls both pieces apart inside the lambda. Clean, readable, one line.

Stack Overflow’s 2024 survey collected responses from over 65,000 developers in 185 countries. Kotlin ranked as the 4th most admired language, and its destructuring declarations are one of those small features that contribute to that satisfaction score.

Using mapIndexed With toMap

Different approach, same result:

` val colorByPosition = colors.mapIndexed { index, value -> index to value }.toMap() `

This creates an intermediate list of Pairs before converting. Slightly less efficient than withIndex().associate{} for large lists, but the intent is clear when you need the indexed transformation step for other processing too.

Pick withIndex when the index is for the map key only. Pick mapIndexed when you also need the index for transforming the value, or when the indexed list serves other purposes besides map creation.

List to Map Conversion in Kotlin Compared to Java

maxresdefault How To Convert A List To Map In Kotlin

Both languages compile to JVM bytecode. Runtime performance is roughly the same. The difference is how much code you write to get there.

Google’s crash analytics data shows that NullPointerExceptions cause over 70% of crashes in Java Android apps. Kotlin’s null safety addresses this at the type system level, which also affects how safely you can work with collection transformations and map lookups.

Kotlin associate vs Java Collectors.toMap

Kotlin version:

` val users = listOf(User(1, "Alice"), User(2, "Bob")) val map = users.associateBy { it.id } `

Java equivalent:

` List<User> users = List.of(new User(1, "Alice"), new User(2, "Bob")); Map<Integer, User> map = users.stream() .collect(Collectors.toMap(User::getId, Function.identity())); `

The Java version requires a Stream pipeline, a Collector import, and Function.identity(). Kotlin's is one line with a trailing lambda. The JetBrains State of Developer Ecosystem Report 2024 surveyed over 23,000 developers, and Kotlin's concise collection handling remains one of its most praised features.

Null Safety During Map Operations

JetBrains data shows a 45% reduction in null-reference bugs on projects using Kotlin’s strict null safety. This matters for collection conversions because map lookups return nullable types by default.

` // Kotlin - compiler forces you to handle null val name: String? = map[someKey] // returns String? val safeName = name ?: "default"

// Java – nothing stops you from ignoring null String name = map.get(someKey); // returns String, but might be null name.length(); // potential NullPointerException `

When building maps from lists using Kotlin data classes, the compiler tracks nullability through the entire chain. If your list contains nullable elements, the type system propagates that information into the resulting map’s value type.

groupBy vs Collectors.groupingBy

FeatureKotlin groupByJava Collectors.groupingBy
SyntaxSingle function callStream + Collector chain
Return typeMap<K, List>Map<K, List>
Downstream operationsChain with mapValuesPass downstream Collector
Null handlingType-safe nullabilityRuntime NPE risk

Java’s approach is more composable when you need multiple downstream collectors. Kotlin’s approach is more readable for the common case. If you’re comparing the two languages for a new project, the trade-offs between Kotlin and Java extend beyond collections into null safety, coroutines, and overall code volume.

Shopify, McDonald’s, and Duolingo are among the companies that have adopted Kotlin Multiplatform for sharing business logic. When collection operations like list-to-map conversions live in shared modules, Kotlin’s type safety and concise syntax directly reduce bugs across platforms.

For teams coming from Java, the migration path is smooth. Kotlin’s full interoperability means you can call Java collection methods from Kotlin and vice versa. You can gradually replace Collectors.toMap() calls with associateBy as files get converted, with zero risk to existing back-end or front-end code.

FAQ on List To Map In Kotlin

What is the fastest way to convert a list to map in Kotlin?

Use associateBy for the best performance. It avoids creating intermediate Pair objects, unlike associate. The function inserts elements directly into a LinkedHashMap using your key selector lambda. All standard approaches run in O(n) time.

What happens with duplicate keys when converting a Kotlin list to map?

The last value silently wins. Functions like associate and associateBy overwrite earlier entries without throwing errors. If you need all values preserved, use groupBy instead, which returns a Map<K, List>.

What is the difference between associate and associateBy in Kotlin?

associate takes a lambda returning a key-value Pair, giving you full control over both sides. associateBy only requires a key selector, keeping the original list element as the value. Use associateBy when indexing objects by a property like ID.

How do you convert a list of pairs to a map in Kotlin?

Call toMap() directly on any List<Pair>. This works well after zipping two lists together or when functions return pairs. The Kotlin standard library handles the conversion into a read-only map automatically.

Can you preserve insertion order when converting a list to map?

Yes. All Kotlin collection conversion functions (associate, associateBy, groupBy) return a LinkedHashMap by default. This preserves the original list order in the resulting map's iteration sequence without any extra configuration.

How does Kotlin groupBy differ from associateBy?

associateBy keeps one value per key, dropping duplicates silently. groupBy collects all elements sharing the same key into a list. Use groupBy when multiple list items map to the same key and you need every value.

How do you include the list index in a Kotlin map conversion?

Combine withIndex() and associate to use the index as a map key. You can also use mapIndexed to create index-based pairs, then call toMap(). Both approaches give you access to each element's position.

What is buildMap in Kotlin and when should you use it?

buildMap (available since Kotlin 1.6) provides a MutableMap receiver inside a builder lambda. Use it when you need conditional logic, merging, or pre-sizing. It returns a read-only map after the builder block completes.

How does Kotlin list to map compare to Java Collectors.toMap?

Kotlin’s associateBy does in one line what Java needs a Stream pipeline, Collector import, and Function.identity() call to do. Both compile to JVM bytecode with similar runtime performance. Kotlin's version is just less verbose.

Is associateWith the same as associateBy in Kotlin?

No. associateBy uses list elements as values and the lambda produces keys. associateWith flips this, using list elements as keys while the lambda produces values. They solve opposite mapping directions from the same source list.

Conclusion

Getting list to map in Kotlin right comes down to picking the correct function for your data shape. associateBy handles most cases where keys are unique. groupBy is your safety net when they're not.

The duplicate key behavior alone is worth memorizing. Silent data loss from associate or associateBy has caused real production bugs that are painful to debug.

Performance-wise, all these Kotlin collection operations run in linear time. The meaningful difference is Pair allocation in associate versus direct insertion in associateBy. For most codebases, either works fine.

Use buildMap when conditional logic gets complicated. Use mapIndexed with toMap` when position matters. And if you’re migrating from Java’s Collectors.toMap, you’ll write less code for the same result.

Know your keys. Pick your function. Let the Kotlin standard library do the rest.

50218a090dd169a5399b03ee399b27df17d94bb940d98ae3f8daff6c978743c5?s=250&d=mm&r=g How To Convert A List To Map In Kotlin

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.