搞懂 Kotlin 的 List、Set、Map、HashMap、LinkedHashMap,以及 asSequence() 的底层原理与实战场景。

一、集合家族总览

在 Kotlin 中,集合是最常用的数据结构之一,主要分为三类:

类型 用途 是否有序 是否允许重复 常见实现
List 有序队列 ArrayList, MutableList
Set 去重集合 ⚠️(看实现) HashSet, LinkedHashSet
Map 键值对映射表 ⚠️(看实现) key❌ value✅ HashMap, LinkedHashMap

可变 vs 只读

  • List, Set, Map只读视图(不能增删改)

  • MutableList, MutableSet, MutableMap可变集合

二、各集合的核心特征

1. List / MutableList

👉 有序可重复,像"排队单子"。

Kotlin 复制代码
val nums = mutableListOf(1, 1, 2)
nums.add(3)
nums.remove(1)         // 删除第一个 1
nums.removeAll { it == 1 } // 删除所有 1
println(nums)          // [2, 3]

常用实现:

  • ArrayList() → 最常见

  • CopyOnWriteArrayList() → 多线程读多写少

2. Set / MutableSet

👉 自动去重。无论你加几次同样元素,只留一份。

Kotlin 复制代码
val set = mutableSetOf(1, 1, 2)
println(set) // [1, 2]

常见实现:

  • HashSet → 无序,高效

  • LinkedHashSet → 按插入顺序保存

  • TreeSet → 自动排序(需要可比较类型)

3. Map / MutableMap

👉 键值对结构(key → value),key 唯一,后写会覆盖前写。

Kotlin 复制代码
val map = mutableMapOf<Int, String>()
map[1] = "A"
map[1] = "B" // 覆盖
println(map) // {1=B}

常见实现:

  • HashMap:高效、无序

  • LinkedHashMap:保序

  • ConcurrentHashMap:多线程安全

三、关键集合实现对比表

类型 是否有序 是否去重 是否可变 说明
listOf() 只读列表
mutableListOf() 可增删改
setOf() ⚠️ 只读去重集合
mutableSetOf() ⚠️ 可增删改的去重集合
mapOf() ⚠️ ✅(key) 只读映射表
mutableMapOf() ⚠️ ✅(key) 可增删改映射表
HashMap ✅(key) 无序高效
LinkedHashMap ✅(key) 有序可改

四、实战:事件队列模型(真实场景)

场景:机器人上报"事件",同一设备可能重复上报。

Kotlin 复制代码
data class DeviceRoute(
    val targetId: String,
    val command: String
)

// 允许重复、保序
private val targetIdList = mutableListOf<DeviceRoute>()

fun addEvent(id: String, cmd: String) {
    targetIdList.add(DeviceRoute(id, cmd))
}

/** 按 command 获取全部 id(允许重复) */
fun getTargetIds(command: String): List<String> {
    return targetIdList.asSequence() // ← 关键点在这里
        .filter { it.command == command }
        .map { it.targetId }
        .toList()
}

/** 删除一个事件(只删第一个匹配项) */
fun removeOne(id: String, cmd: String): Boolean {
    return targetIdList.remove(DeviceRoute(id, cmd))
}

/** 删除所有匹配事件 */
fun removeAll(id: String, cmd: String): Boolean {
    return targetIdList.removeAll { it.targetId == id && it.command == cmd }
}

👉 用 List 因为要保留所有事件(包括重复),

👉 Set 会去重,不适合事件流;

👉 Map key 唯一,也会覆盖旧数据。

五、重点:asSequence() 到底干嘛?

很多人一开始看到这句:

Kotlin 复制代码
targetIdList.asSequence()
    .filter { it.command == command }
    .map { it.targetId }
    .toList()

会疑惑:"asSequence() 有啥用?"

✅ 1. 定义

asSequence() 会把集合转为一个 惰性(lazy)序列

它不会立刻执行 filter/map,而是等到"终止操作"再逐个计算。

✅ 2. 原理对比

不用 asSequence:
Kotlin 复制代码
val result = list
    .filter { it > 10 } // 生成一个新 List
    .map { it * 2 }     // 再生成一个新 List
    .toList()           // 最后又生成一个 List

会构建多个中间集合,占内存、效率低。

用 asSequence:
Kotlin 复制代码
val result = list.asSequence()
    .filter { it > 10 } // 惰性:不马上创建集合
    .map { it * 2 }     // 按需逐个处理
    .toList()           // 到这里才一次性收集结果

只遍历一次列表,更高效,尤其对大数据集合。

✅ 3. 终止操作(trigger 执行)

只有当调用以下之一时才真正执行:

  • 收集:toList(), toSet(), toCollection(...)

  • 查找:first(), firstOrNull(), any(), count()

  • 遍历:forEach, onEach { }.toList()

例如:

Kotlin 复制代码
val res = list.asSequence()
    .filter { it > 10 }
    .map { it * 2 }
    .forEach { println(it) } // 到这里才真正遍历

✅ 4. 优点

优点 说明
🚀 惰性执行 不创建中间集合,效率更高
🧠 可读性强 链式写法直观
💾 节省内存 对大数据集合友好
🔄 保留顺序 不会乱序执行
✅ 与集合方法兼容 可随时 .asSequence() / .toList() 切换

✅ 5. 注意事项

  • Sequence 不是并行流(不像 Java Stream);

  • 如果数据量小,普通集合操作和 Sequence 性能几乎一样;

  • 大量链式计算时 Sequence 更合适。

六、不同结构的典型使用建议

场景 推荐结构 说明
有序、可重复的事件 MutableList 保留所有事件
唯一元素集合 MutableSet / LinkedHashSet 去重场景
键值查表 HashMap / LinkedHashMap 查找快
数据多、要链式过滤 asSequence() 避免中间集合
多线程访问 CopyOnWriteArrayList / ConcurrentHashMap 安全

七、结语:如何选择集合?

你的需求 推荐
要顺序 + 重复 MutableList
要顺序 + 不重复 LinkedHashSet
不关心顺序 + 不重复 HashSet
要查表(key→value) HashMap / LinkedHashMap
想延迟计算、优化性能 .asSequence()

✅ "List 保序可重复,Set 去重,Map 查表,Sequence 优化链路。"

🎯 最后一句话总结

List 是队列,Set 是名单,Map 是字典,asSequence() 是让它们"边走边算"的聪明处理器。

相关推荐
明道源码4 小时前
Kotlin 面向对象编程、主构造函数、次构造函数、伴生对象、数据类、继承
kotlin·1024程序员节
遥远_4 小时前
Spring Boot微服务健康检测:保障系统稳定性的关键实践
spring boot·微服务·1024程序员节·健康检测
程序员杰哥4 小时前
如何使用Postman做接口自动化测试及完美的可视化报告?
自动化测试·软件测试·python·测试工具·jenkins·postman·1024程序员节
计算机毕业设计小帅4 小时前
【2026计算机毕业设计】基于Django的智慧办公hr招聘辅助管理系统
1024程序员节
千歌叹尽执夏4 小时前
Quartus25.3:Agilex5A EMIF学习调用(DDR5)
fpga开发·1024程序员节·ddr5·agilex5·emif
计算机毕业设计小帅4 小时前
【2026计算机毕业设计】基于Django的新闻资讯平台的设计与实现
1024程序员节
武子康4 小时前
Java-159 MongoDB 副本集容器化 10 分钟速查卡|keyfile + –auth + 幂等 init 附 docker-compose
java·数据库·mongodb·docker·性能优化·nosql·1024程序员节
峥嵘life4 小时前
Android EDLA开发认证说明和开发流程
开发语言·1024程序员节
含目的基因的质粒4 小时前
Python的数据容器
1024程序员节