Kotlin List 转 Map:转换与代码加速指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

从列表到映射:为什么这很重要以及如何正确操作?

\n\n

想象一下:您正在开发一个 Kotlin 应用,从 API 获取了一个用户列表。您需要根据 ID 快速找到某个用户。每次都遍历列表——O(n),当元素超过 1000 个时,这会变得非常痛苦。而通过 Map 查找——是 O(1)。差异巨大。

\n\n

"How to convert List to Map in Kotlin?" 这个问题是 Stack Overflow 上最热门的问题之一。这并非没有原因:错误的转换可能导致数据丢失、性能下降或奇怪的 bug。今天,我们将介绍 5 种转换方法,从简单到高级,并了解如何将代码速度提升 10 倍。

\n\n

基础方法:associate、toMap 和 groupBy

\n\n

1. 经典方法:associate——最常见的选择

\n

associate 函数是转换之王。它接受一个 lambda,返回一个键值对。

\n\n
data class User(val id: Int, val name: String, val age: Int)\n\nval users = listOf(\n    User(1, "安娜", 25),\n    User(2, "鲍里斯", 30),\n    User(3, "维克多", 22)\n)\n\n// 最简单的情况:id -> name\nval idToNameMap: Map<Int, String> = users.associate { it.id to it.name }\nprintln(idToNameMap) // {1=安娜, 2=鲍里斯, 3=维克多}\n\n// 根据 id 获取完整对象\nval userMap: Map<Int, User> = users.associate { it.id to it }\nprintln(userMap[2]) // User(id=2, name="鲍里斯", age=30)\n
\n\n

重要提示:如果列表中出现重复键(associate 会用最后一个覆盖),您甚至可能不会注意到。请务必小心!

\n\n

2. toMap——当您已经有一个键值对集合时

\n

如果您预先创建了一个 Pair<K, V> 列表,请使用 toMap()。

\n\n
val pairs = listOf(\n    1 to "安娜",\n    2 to "鲍里斯",\n    3 to "维克多"\n)\n\nval mapFromPairs: Map<Int, String> = pairs.toMap()\nprintln(mapFromPairs) // {1=安娜, 2=鲍里斯, 3=维克多}\n
\n\n

toMap 也适用于 Map.Entry 集合和其他键值对迭代器。

\n\n

3. groupBy——当一个键对应多个值时

\n

有时需要根据键对元素进行分组。例如,按年龄对用户进行分组。

\n\n
val usersByAge: Map<Int, List<User>> = users.groupBy { it.age }\n// 结果:{25=[User(id=1, name=安娜, age=25)], 30=[User(id=2, name=鲍里斯, age=30)], 22=[User(id=3, name=维克多, age=22)]}\n
\n\n

groupBy 返回 Map<K, List<V>>。非常适合分析、过滤和构建报告。

\n\n

高级技巧:当标准方法不够用时

\n\n

4. associateBy——如果您只需要键,而值就是元素本身

\n

associateBy 函数是 associate { key to it } 的同义词,但可读性更好。

\n\n
val userMapById: Map<Int, User> = users.associateBy { it.id }\n// 等同于:users.associate { it.id to it }\nprintln(userMapById[1]) // User(id=1, name=安娜, age=25)\n
\n\n

建议:当您需要创建"键 → 对象本身"的字典时,使用 associateBy。代码会更简洁。

\n\n

5. 自定义转换并处理重复项

\n

假设您有一个订单列表,多个订单可能具有相同的 ID(例如,不同版本)。标准的 associate 会直接覆盖。但如果需要保留所有订单呢?

\n\n
data class Order(val id: Int, val amount: Double, val version: Int)\n\nval orders = listOf(\n    Order(1, 100.0, 1),\n    Order(1, 150.0, 2), // id 重复,但版本不同\n    Order(2, 200.0, 1)\n)\n\n// 方案 1:按 id 分组\nval ordersGrouped: Map<Int, List<Order>> = orders.groupBy { it.id }\n// {1=[Order(1, 100.0, 1), Order(1, 150.0, 2)], 2=[O                

博客

书籍推荐