搞懂 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() 是让它们"边走边算"的聪明处理器。

相关推荐
FunnySaltyFish17 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
Kapaseker1 天前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker2 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
A0微声z4 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton4 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream5 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam5 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker5 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
糖猫猫cc6 天前
Kite:两种方式实现动态表名
java·kotlin·orm·kite
如此风景6 天前
kotlin协程学习小计
android·kotlin