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

Kotlin序列

序列(Sequences)

序列是一种容器,其中的对象不是事先存储的,而是在迭代过程中动态生成的。 这意味着这些对象只有在真正需要使用时才会被处理:也就是说,序列是惰性执行的(lazy evaluation),每一步不会立刻产生中间结果。

序列提供了与 Iterable 相同的函数:我们可以对其进行过滤、映射、排序等操作,但在底层的实现方式上有所不同。对于 Iterable,每一步操作都对整个集合执行并返回一个新的中间集合;而对于 Sequence,每个操作都是逐个元素地链式执行,直到最终结果被请求时才真正开始处理。

这带来了两个优势:

  1. 序列可以是无限的:我们可以通过初始值和一个函数来定义一个序列,例如无限增长的数列。

  2. 避免中间集合的创建:多个操作(如过滤、转换等)在序列中是链式按需执行的,不需要每一步都生成新的集合。


创建序列的方法

1. 从元素创建

使用 sequenceOf() 函数,从给定的元素生成序列:

val sequenceOfStrings = sequenceOf("one", "two", "three", "four")
val sequenceOfInts = sequenceOf(1, 2, 3, 4)

2. 从可迭代对象(Iterable)创建

可以使用 asSequence() 将任何集合转换为序列:

val listOfStrings = listOf("one", "two", "three", "four")
val listOfInts = listOf(1, 2, 3, 4)val sequenceOfStrings = listOfStrings.asSequence()
val sequenceOfInts = listOfInts.asSequence()

解释:这会将已有的 List 或其他集合转换为 Sequence,以便惰性处理元素。


3. 从函数创建

使用 generateSequence(),它接收一个初始值(种子)和一个函数,根据规则生成一个(可能无限的)序列:

val sequenceOfEvenNumbers = generateSequence(1) { it + 1 }.filter { it % 2 == 0 }.take(5)
println(sequenceOfEvenNumbers.toList()) // [2, 4, 6, 8, 10]

解释:这段代码生成了一个从 1 开始不断加 1 的序列,过滤出偶数,并取前 5 个。


4. 从代码块分块生成

使用 sequence {} 代码块,配合 yield()yieldAll() 按需产生元素:

val evenNumbersSequence = sequence {yield(2)yieldAll(listOf(4, 6))yieldAll(generateSequence(8) { it + 2 })
}
println(evenNumbersSequence.take(5).toList()) // [2, 4, 6, 8, 10]

解释:这个序列依次生成了 2,4,6,然后从 8 开始生成无限个偶数。


一、序列操作的两大分类:无状态 vs 有状态

无状态操作(Stateless)

定义:对每个元素独立处理,不依赖之前元素或上下文。

方法用途示例代码
map()对每个元素应用变换sequenceOf(1, 2, 3).map { it * 2 }[2, 4, 6]
filter()过滤符合条件的元素sequenceOf(1, 2, 3, 4).filter { it % 2 == 0 }[2, 4]
take(n)取前 n 个元素sequenceOf(1, 2, 3, 4).take(2)[1, 2]
drop(n)跳过前 n 个元素sequenceOf(1, 2, 3, 4).drop(2)[3, 4]
这些操作通常开销较小,并且可以尽早终止处理。

有状态操作(Stateful)

定义:需要维护中间状态(缓存、计数、排序等),通常必须遍历整个序列。

方法用途示例代码
sorted()排序(需收集全部元素)sequenceOf(3, 1, 2).sorted()[1, 2, 3]
distinct()去重(需跟踪已出现的值)sequenceOf(1, 2, 1).distinct()[1, 2]
chunked(n)将序列划分为多个块sequenceOf(1,2,3,4,5).chunked(2)[[1,2], [3,4], [5]]

二、序列操作的阶段:中间 vs 终端

中间操作(Intermediate)

特点:惰性执行,不立刻处理元素,只是构造操作链。返回新的 Sequence

方法用途示例
map()转换元素sequence.map { it * 2 }
filter()过滤元素sequence.filter { it > 0 }
take() / drop()取/跳前几个sequence.take(3)
sorted()排序sequence.sorted()
这些方法只有在终端操作触发时才执行!

终端操作(Terminal)

特点:触发执行,返回结果(如集合、单个值等),整个序列会被遍历或处理。

方法用途示例返回值类型
toList()转换为 Listsequence.toList()List<T>
sum()求和sequenceOf(1,2,3).sum()Int
count()元素个数sequence.count()Int
first() / last()获取首/尾元素sequence.first()T
forEach()遍历每个元素sequence.forEach { println(it) }Unit
reduce() / fold()累加/聚合sequence.reduce { acc, e -> acc + e }T

三、完整示例:理解延迟执行与触发机制

fun main() {val result = sequenceOf(1, 2, 3, 4, 5).map {println("map $it")it * 2}.filter {println("filter $it")it > 5}.take(2) // 限制只取前两个符合条件的元素.toList() // 触发执行println("Result: $result")
}

序列与集合的处理方式对比

Iterable急切(eager)执行

每个操作都在所有元素上执行,并产生中间集合。

val withIterator = (1..10).filter { print("Filter: $it, "); it % 2 == 0 }.map { print("Mapping: $it, "); it * 2 }.take(3)println()
// 输出:
// Filter: 1, Filter: 2, ... Filter: 10,
// Mapping: 2, Mapping: 4, Mapping: 6, Mapping: 8, Mapping: 10
// 结果:[4, 8, 12]

总共执行了:

  • 10 次 filter

  • 5 次 map

  • 3 次 take
    总计:18 次操作


Sequence惰性(lazy)执行

每个元素在执行链中逐个被处理,没有中间集合。

val withSequence = (1..10).asSequence().filter { print("Filter: $it, "); it % 2 == 0 }.map { print("Mapping: $it, "); it * 2 }.take(3).toList()println()
// 输出:
// Filter: 1, Filter: 2, Mapping: 2, Filter: 3, Filter: 4, Mapping: 4, ...
// 结果:[4, 8, 12]

📊 总共执行了:

  • 6 次 filter

  • 3 次 map

  • 3 次 take
    总计:12 次操作


总结

Sequences(序列) 提供了强大且高效的方式来处理数据集合,特别适合于:

  • 大型集合或数据流

  • 多步链式处理的场景

  • 惰性处理需求

  • 表达无限序列或生成序列的逻辑

当你需要优化集合操作性能时,考虑使用 Sequence 是一个很好的选择。

http://www.dtcms.com/a/285984.html

相关文章:

  • 外网访问基于 Git 的开源文件管理系统 Gogs
  • CentOS7下的ElasticSearch部署
  • SQL映射文件
  • elasticsearch+logstash+kibana+filebeat实现niginx日志收集(未过滤日志内容)
  • 树的重心相关概念证明
  • MyUI表单VcForm组件文档
  • 组件-多行文本省略-展开收起
  • VMC850立式加工中心Y轴传动机械结构设计cad【7张】三维图+设计说明书
  • 多模态大模型研究每日简报(2025-07-17)
  • 设计循环队列oj题(力口622)
  • 基于现代R语言【Tidyverse、Tidymodel】的机器学习方法与案例分析
  • OSPF路由协议的协商过程
  • (八)复习(拆分微服务)
  • 快速了解pycharm
  • 微服务基础环境搭建-centos7
  • HIVE实战处理(二十四)留存用户数
  • 第8天 | openGauss中一个数据库可以存储在多个表空间中
  • mybatisdemo(黑马)
  • 数据结构-3(双向链表、循环链表、栈、队列)
  • 前端-CSS (样式引入、选择器)
  • 7月18日总结
  • 深度学习之----对抗生成网络-pytorch-CycleGAN-and-pix2pix
  • Jenkins pipeline 部署docker通用模板
  • drm驱动学习(一)sunxi_drm初始化
  • 【leetcode】3201. 找出有效子序列的最大长度(1)
  • PyCharm 高效入门指南(核心模块详解二)
  • RoboBrain 2.0(具身智能论文阅读)
  • 笔试——Day12
  • 阿里云alicloud liunux3-安装docker
  • Python编程进阶知识之第二课学习网络爬虫(selenium)