在 Kotlin 中,List
、Set
和 Map
是三种核心集合类型,它们分别适用于不同的场景,具有独特的特性和操作方式。以下是它们的详细对比与使用指南:
1. List(列表)
核心特性
• 有序:元素按插入顺序存储。
• 可重复:允许存在相同值的元素。
• 索引访问:通过下标(get(index)
或 [index]
)快速访问元素。
分类
• 不可变列表:List<T>
,创建后不可修改。
val immutableList = listOf("A", "B", "C")
• 可变列表:MutableList<T>
,支持增删改。
val mutableList = mutableListOf(1, 2, 3)
mutableList.add(4) // [1, 2, 3, 4]
常用操作
方法 | 说明 | 示例 |
---|---|---|
size | 获取元素数量 | list.size → 3 |
get(index) | 获取指定位置元素 | list[0] → “A” |
indexOf(element) | 查找元素首次出现的索引 | list.indexOf("B") → 1 |
subList(from, to) | 截取子列表 | list.subList(1, 3) → [“B”, “C”] |
map { ... } | 转换每个元素 | list.map { it.length } → [1, 1, 1] |
filter { ... } | 过滤符合条件的元素 | list.filter { it > "B" } → [“C”] |
适用场景
• 需要保留元素顺序(如时间序列数据)。
• 允许重复值(如购物车商品列表)。
• 通过索引快速访问(如分页数据)。
2. Set(集合)
核心特性
• 无序:元素存储顺序不固定。
• 唯一性:元素不可重复(自动去重)。
• 快速存在性检查:基于哈希表或树结构优化查询效率。
分类
• 不可变集合:Set<T>
。
val immutableSet = setOf("A", "B", "A") // 实际存储 ["A", "B"]
• 可变集合:MutableSet<T>
。
val mutableSet = mutableSetOf(1, 2)
mutableSet.add(3) // [1, 2, 3](具体顺序可能变化)
实现类对比
类型 | 底层实现 | 特性 |
---|---|---|
HashSet | 哈希表 | 默认实现,高效查找,无序 |
LinkedHashSet | 链表+哈希表 | 保持插入顺序 |
TreeSet | 红黑树 | 元素按自然顺序排序 |
常用操作
方法 | 说明 | 示例 |
---|---|---|
contains(element) | 检查元素是否存在 | set.contains("A") → true |
union(otherSet) | 取并集 | set1.union(set2) → 合并后的集合 |
intersect(otherSet) | 取交集 | set1.intersect(set2) → 共同元素 |
minus(element) | 移除指定元素 | set.minus("A") → 新集合不包含 “A” |
适用场景
• 需要去重的数据集(如用户ID集合)。
• 快速判断元素是否存在(如屏蔽词过滤)。
• 集合运算(如权限交集、并集)。
3. Map(映射)
核心特性
• 键值对存储:每个元素由键(Key)和值(Value)组成。
• 键唯一性:键不可重复,值可以重复。
• 快速键查找:基于键的哈希或树结构优化查询。
分类
• 不可变映射:Map<K, V>
。
val immutableMap = mapOf(1 to "A", 2 to "B")
• 可变映射:MutableMap<K, V>
。
val mutableMap = mutableMapOf(1 to "A")
mutableMap[2] = "B" // {1="A", 2="B"}
实现类对比
类型 | 底层实现 | 特性 |
---|---|---|
HashMap | 哈希表 | 默认实现,高效查找,无序 |
LinkedHashMap | 链表+哈希表 | 保持插入顺序或访问顺序 |
TreeMap | 红黑树 | 键按自然顺序排序 |
常用操作
方法 | 说明 | 示例 |
---|---|---|
keys / values | 获取所有键或值 | map.keys → [1, 2] |
get(key) | 根据键获取值 | map[1] → “A” |
getOrDefault(key, default) | 安全获取值(避免空指针) | map.getOrDefault(3, "Unknown") → “Unknown” |
put(key, value) | 添加或更新键值对 | map.put(3, "C") → {1=“A”, 2=“B”, 3=“C”} |
remove(key) | 删除指定键的条目 | map.remove(2) → {1=“A”} |
适用场景
• 键值关联数据(如用户信息表,键为用户ID)。
• 快速通过键访问值(如缓存系统)。
• 需要键排序的场景(如排行榜按分数排序)。
三者的对比总结
特性 | List | Set | Map |
---|---|---|---|
元素唯一性 | 允许重复 | 唯一 | 键唯一,值可重复 |
顺序性 | 有序 | 无序(LinkedHashSet 除外) | 无序(LinkedHashMap /TreeMap 除外) |
访问方式 | 索引 | 存在性检查 | 键查找 |
典型实现类 | ArrayList , LinkedList | HashSet , TreeSet | HashMap , TreeMap |
内存开销 | 较低 | 较高(需存储哈希结构) | 最高(键值对存储) |
高级技巧
-
集合转换:
val list = listOf(1, 2, 2, 3) val set = list.toSet() // 去重 → [1, 2, 3] val map = list.associateWith { it * 10 } // {1=10, 2=20, 3=30}
-
空安全操作:
val nullableList: List<Int>? = null val safeSize = nullableList?.size ?: 0 // 避免空指针
-
链式操作:
val result = listOf("apple", "banana") .filter { it.length > 5 } .map { it.uppercase() } .toSet() // {"BANANA"}
通过合理选择 List
、Set
或 Map
,可以高效解决数据存储和检索需求,同时利用 Kotlin 丰富的扩展函数简化代码逻辑。