当前位置: 首页 > news >正文

Kotlin杂学:集合的学习之路

1. 集合体系架构

1.1 继承层级结构

Kotlin 的集合体系建立在Iterable接口之上。

  • Iterable: 迭代器接口,支持for循环遍历。

  • Collection: 基础集合接口,定义了sizeisEmpty()contains()等只读属性。

  • List/Set: 继承自Collection,分别代表有序列表和无序去重集。

  • Map: 独立体系,存储键值对。

1.2 与 Java 集合的设计哲学对比

  • Java: 所有的集合都是可变的(Mutable),安全性全靠开发者的自觉或Collections.unmodifiableList

  • Kotlin: 将接口拆分为只读(Read-only)和可变(Mutable)。

    • 例如:List接口只有get,没有add。想修改必须使用MutableList

1.3 核心接口定义

Kotlin 通过接口层级实现了“读写分离”:

  • List<out T>: 只读列表。

  • MutableList<T>: 继承自ListMutableCollection,增加了add/remove


2. 不可变与可变集合

2.1 & 2.2 概念与特性

  • 只读集合: 并不代表底层数据不可变,而是当前引用没有修改权限

  • 可变集合: 拥有完整的增删改查权限。

2.3 创建方式与代码实例

// 1. listOf: 创建只读列表 (底层通常是 Arrays.ArrayList) val readOnlyList = listOf("Kotlin", "Java") // 2. mutableListOf: 创建可变列表 (底层是 ArrayList) val mutableList = mutableListOf("Apple") mutableList.add("Banana") // 3. buildList (Kotlin 1.4+): 在作用域内可变,返回后不可变 val constructedList = buildList { add("A") add("B") if (true) add("C") } // 此时 constructedList 是只读的 List<String>

2.4 底层实现与内存模型

在 JVM 上,listOf(1, 2)编译后会生成类似Arrays.asList的对象,它比普通的ArrayList更轻量,因为它不需要预留扩容空间。


3. List 深度解析

3.1 访问操作

val list = listOf("A", "B", "C") // 安全取值:避免 IndexOutOfBoundsException val item = list.getOrNull(5) ?: "None" // 索引越界返回 null,通过 ?: 给默认值 // 语义化取值 val firstItem = list.first() // 第一个 val lastItem = list.lastOrNull { it == "D" } // 最后一个符合条件的,没有则返回 null

3.3 子列表操作

val numbers = (0..10).toList() // slice: 使用区间截取 val sliced = numbers.slice(1..3) // [1, 2, 3] // take/drop: 获取或丢弃 val firstThree = numbers.take(3) // [0, 1, 2] val lastSeven = numbers.drop(3) // [3, 4, 5, 6, 7, 8, 9, 10]

4. Set 深度解析

4.1 & 4.2 实现类与去重

  • HashSet: 无序,查询极快(O(1))。

  • LinkedHashSet:Kotlin 默认setOf),保留插入顺序。

4.3 集合运算

val a = setOf(1, 2, 3) val b = setOf(3, 4, 5) println(a intersect b) // [3] 交集 println(a union b) // [1, 2, 3, 4, 5] 并集 println(a - b) // [1, 2] 差集 (A中有,B中没有)

4.5 去重技巧

val users = listOf("apple", "apply", "banana") // distinctBy: 根据特征去重 val result = users.distinctBy { it.length } // 长度相同的只保留第一个 -> [apple, banana]

5. Map 深度解析

5.2 访问操作 (核心推荐)

val scores = mutableMapOf("Math" to 90) // getOrPut: 缓存模式的王者 // 如果有 key 就返回;没有就执行 Lambda 存入并返回结果 val englishScore = scores.getOrPut("English") { 85 } // getValue: 如果 Key 不存在直接抛异常,比 get()!! 更安全地表达“这里必须有值” val math = scores.getValue("Math")

5.4 遍历方式

// 利用解构声明遍历,代码极其整洁 for ((subject, score) in scores) { println("$subject 成绩是: $score") }

6. 集合操作符详解 (博客灵魂)

6.2 映射操作

val data = listOf("1", "2", "3", "abc") // mapNotNull: 变换的同时过滤掉结果为 null 的项 val ints = data.mapNotNull { it.toIntOrNull() } // [1, 2, 3] // flatMap: 1对多变换并铺平 val chars = listOf("AB", "CD").flatMap { it.toList() } // [A, B, C, D]

6.4 分组与聚合

val words = listOf("Apple", "Apricot", "Banana") val groups = words.groupBy { it.first() } // {A=[Apple, Apricot], B=[Banana]} // fold: 带初始值的累加 val sum = listOf(1, 2, 3).fold(10) { acc, i -> acc + i } // 10+1+2+3 = 16

6.7 分块与窗口

val nums = (1..5).toList() println(nums.chunked(2)) // [[1, 2], [3, 4], [5]] 分组 println(nums.windowed(2)) // [[1, 2], [2, 3], [3, 4], [4, 5]] 滑动窗口

7. 序列 (Sequence) 性能优化

7.1 概念对比

  • Iterable (急切):filter生成一个 List,map又生成一个 List。大数据量时极度浪费内存。

  • Sequence (惰性): 元素一个一个走完所有流程。

// 只有执行 toList() 时,逻辑才会真正运行 val sequenceResult = hugeList.asSequence() .filter { it % 2 == 0 } .map { it * 2 } .take(10) .toList()

8. 与 Java 互操作

8.3 平台类型陷阱

当 Java 返回一个List<String>时,Kotlin 会将其视作List<String!>(平台类型)。

  • 风险: 这个 List 可能是 null,里面的元素也可能是 null。

  • 对策: 显式声明类型,如val list: List<String> = javaService.getList()


9. 源码解析 (进阶加分项)

9.2 map 操作符源码逐行解析

public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> { // 1. 根据当前集合大小预设目标 ArrayList 的容量(优化性能) return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform) } public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C { for (item in this) { // 2. 核心就是一个简单的 for 循环 destination.add(transform(item)) } return destination }

源码心得: Kotlin 的集合操作符之所以性能好,是因为它大量使用了inline(内联)。这意味着你的 Lambda 表达式在编译后并不会产生额外的函数调用开销。


总结:Kotlin 集合并不是对 Java 集合的重写,而是一套精妙的扩展函数库。它通过读写分离的接口解决了安全问题,通过内联函数解决了性能问题,通过丰富的操作符解决了开发效率问题。

http://www.jsqmd.com/news/569446/

相关文章:

  • Qwen3-ASR-0.6B部署指南:Ubuntu20.04环境配置全流程
  • 3个核心优势让研究者实现智能OCR全场景覆盖:Pix2Text开源替代方案详解
  • 2026年人工智能与算力国际学术会议(ICAICP 2026)
  • **发散创新:基于Python的预测性维护系统实战解析**在工业物联网(
  • tao-8k部署避坑指南:Xinference日志排查、WebUI访问与调用验证
  • 从NDVI到SAVI:遥感指数计算的演进逻辑与实战场景解析
  • 别再用asyncio硬扛高并发了!无GIL环境下Python原生多线程性能翻倍的6个核心调优参数
  • 长文本处理神器:通义千问3-4B部署教程,轻松分析80万字文档
  • 炉石传说HsMod:55项功能增强插件完全指南
  • Lychee-rerank-mm在音乐推荐中的创新应用
  • FPGA实战:手把手教你用Verilog给NAND Flash数据上把“安全锁”(附完整ECC代码)
  • 三极管 MOS管
  • 如何评估 SEO 优化的成本效益_SEO优化应该重点关注哪些方面
  • Qwen3-TTS多语种语音案例:为一带一路项目制作中英俄阿四语工程安全培训语音
  • Qwen2.5-14B-Instruct多场景落地:像素剧本圣殿赋能有声书编剧与AI配音协同流程
  • Java微服务在Istio中出现“偶发503 no healthy upstream”?7分钟定位Sidecar健康检查盲区与Liveness Probe冲突真相
  • SEO优化建站费用是多少_SEO建站平台有哪些_哪个比较好
  • 利用快马平台AI能力,五分钟构建你的opcore simlify数据处理原型
  • AnimateDiff效果实测:对比不同提示词生成的动态视频质量
  • 数据库课程设计好帮手:Phi-4-mini-reasoning辅助ER图设计与SQL优化
  • 租车宝 token、payload算法分析
  • 云上自动化运维(CloudOps)成熟度
  • 【等保三级Java安全加固实战指南】:20年专家亲授7大高危漏洞修复清单与合规落地路径
  • 手把手教你将自定义视频问答JSON转成EasyR1可用的Parquet数据集
  • HumanoidVerse深度解析:如何通过多模拟器框架实现人形机器人sim2real高效训练
  • 【Code Buddy Agent 实践】国际化最佳实践
  • 激光+视觉+IMU+RTK融合实战:如何用多传感器打造厘米级三维重建系统?
  • Wan2.2-I2V-A14B与AI Agent协同:自主完成图文内容到视频的创作流程
  • Kotlin 2.3.20 正式发布!解构声明不怕写反了
  • Phi-3-mini-4k-instruct-gguf效果实测:128ms首token延迟+98%中文基础任务通过率