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

相关推荐
程序员老刘1 天前
Kotlin vs Dart:当“优雅”变成心智负担,我选择了更简单的 Dart
flutter·kotlin·dart
QING6181 天前
Kotlin协程:Job.cancel() 和 Scope.cancel() 的区别详解!!!
android·kotlin·android jetpack
yBmZlQzJ2 天前
财运到内网穿透域名解析技术机制与中立评估
运维·经验分享·docker·容器·1024程序员节
yBmZlQzJ2 天前
内网穿透工具通过端口转发实现内外网通信
运维·经验分享·docker·容器·1024程序员节
alexhilton2 天前
Jetpack ViewModel内幕:内部机制与跨平台设计
android·kotlin·android jetpack
QING6182 天前
Kotlin Flow 的 emit 和 tryEmit 有什么区别 ?
android·kotlin·android jetpack
数据皮皮侠AI2 天前
数字经济政策工具变量数据(2008-2023)
大数据·数据库·人工智能·笔记·1024程序员节
Kapaseker3 天前
面试官最爱问的 Android 数据传递问题
android·kotlin
娃乐呵3 天前
免费的大批量Excel文档大模型处理数据工具
语言模型·大模型·excel·数据处理
I'm Jie3 天前
Gradle 多模块依赖集中管理方案,Version Catalogs 详解(Kotlin DSL)
android·java·spring boot·kotlin·gradle·maven