首页 > 编程语言 >【Kotlin】函数式编程 ③ ( 早集合与惰性集合 | 惰性集合-序列 | generateSequence 序列创建函数 | 序列代码示例 | take 扩展函数分析 )

【Kotlin】函数式编程 ③ ( 早集合与惰性集合 | 惰性集合-序列 | generateSequence 序列创建函数 | 序列代码示例 | take 扩展函数分析 )

时间:2023-02-18 22:33:04浏览次数:42  
标签:generateSequence 函数 元素 集合 take 序列


文章目录

  • ​​一、及早集合与惰性集合​​
  • ​​二、惰性集合-序列​​
  • ​​三、generateSequence 序列创建函数​​
  • ​​1、函数简介​​
  • ​​2、函数原型​​
  • ​​3、函数简介​​
  • ​​4、使用示例​​
  • ​​四、序列代码示例​​
  • ​​1、使用传统的函数式编程实现​​
  • ​​2、使用序列 Sequence 实现​​
  • ​​3、take 扩展函数分析​​






一、及早集合与惰性集合



及早集合 与 惰性集合 :

  • 及早集合 : Eager Collection , 指的是 List , Map , Set 等集合 , 这些集合创建后 , 需要 将元素提前存储到集合中
  • 惰性集合 : Lazy Collection , 在 集合刚创建时不必将集合元素放进去 , 当使用这些元素时才生成 , 这些 集合元素按需产生 ;

在 惰性集合 中 集合元素的 初始化 是 惰性初始化 ;






二、惰性集合-序列



Kotlin 中提供了一个 惰性集合 , 称为 序列 Sequence ;

在 序列 中 , 不记录元素个数 , 也 不对其内容进行排序

序列中的元素 是由 数据源 产生的 , 其元素个数 可能有无限多个 ;






三、generateSequence 序列创建函数




1、函数简介



“generateSequence” 函数 是 Kotlin 标准库 中的一个函数,属于 Kotlin 的 序列生成器。

“generateSequence” 函数 可以生成一个 惰性序列,并且支持从指定的序列中生成元素。

生成的序列是惰性的,意味着 请求元素时,才会 生成相应的元素。这使得开发者可以在 不需要处理整个序列的情况下,处理序列中的元素。



2、函数原型



Kotlin 提供的 " generateSequence " 标准库函数 , 原型如下 :

/**
* 返回由起始值[seed]和函数[nextFunction]定义的序列,每次迭代时,该函数被调用以根据前一个值计算下一个值
*
* 序列产生值,直到遇到第一个null值。
* 如果[seed]是null,则生成一个空序列。
*
* 该序列可以多次迭代,每次都从[seed]开始。
*
* @see kotlin.sequences.sequence
*
* @sample samples.collections.Sequences.Building.generateSequenceWithSeed
*/
@kotlin.internal.LowPriorityInOverloadResolution
public fun <T : Any> generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence<T> =
if (seed == null)
EmptySequence
else
GeneratorSequence({ seed }, nextFunction)
  • seed: T? 参数 : 该参数是 序列的第一个元素值
  • nextFunction: (T) -> T? 参数 : 该参数是一个 匿名函数 / Lambda 表达式 / 闭包 , 可以 根据前一个值计算出下一个值 ;


3、函数简介



Kotlin 的 generateSequence 函数是一种 生成序列 的方法,它可以生成 可迭代的、有限或无限的序列。



generateSequence 函数 接收两个参数:

  • 起始值 seed
  • 生成下一个值的 匿名函数 nextFunction。


每次迭代时,nextFunction 都会被调用以生成下一个值,并且该序列会不断生成值,直到遇到第一个 null 值。如果起始值为 null,那么将会生成一个空序列。

该序列可以 多次迭代,每次都从起始值开始。这是因为 generateSequence 返回一个实现了 Sequence 接口的对象,这意味着你可以 在多次迭代之间重用该序列。

通过使用 generateSequence,你可以简化代码,提高可读性和可维护性,并且可以 生成更复杂的序列,如斐波那契数列、自然数序列等。



4、使用示例



使用方法 : 使用 “generateSequence” 函数 并 传递一个函数作为参数 ; 函数必须返回 “Nullable” 类型的值,当序列不再生成元素时返回 “null”。

“generateSequence” 函数 是一种高效且灵活的 生成序列 的方法,它可以用于许多应用程序,如 生成指定数量的元素、生成无限循环的序列等。



示例 : 以下代码生成一个从 1 开始的整数序列:

val sequence = generateSequence(1) { it + 1 }
println(sequence.take(10).toList()) // prints [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]






四、序列代码示例



取 从 2 开始的 前 20 个 素数 ;



1、使用传统的函数式编程实现



代码示例 : 下面的代码中 , 从 1 ~ 1000 的区间内查找素数 , 必须将 1000 个元素的集合生成出来 , 然后逐个遍历 ;

/**
* 为 Int 定义扩展函数, 判断接收者是否是素数
*/
fun Int.isPrimeNumber(): Boolean {
// number 参数是被遍历的 接收者集合 的 受检元素
// 符合下面的要求 才会被放入新集合
// 遍历时每个 受检元素 都要 被 [2..number - 1] 区间的数值进行遍历
val isPrimeNumber = (2..this - 1)
// 计算 number 与 [2..number - 1] 区间中的数值 相除的 余数
// 也就是验证 是否 只有 1 和 其本身 可以被其整除
.map { this % it }
// 通过 map 变换计算出的余数
// 不能出现 余数 为 0 的情况
// 一旦出现 就返回 false
.none{it == 0}
return isPrimeNumber
}

fun main() {
val numbers = (2..1000)
.toList() // 将 IntRange 转为 List 集合
.filter { it.isPrimeNumber() } // 筛选出集合中是素数的人
.take(20) // 从筛选出来的数值中取 20 个元素

println(numbers)
}

执行结果 :

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]

【Kotlin】函数式编程 ③ ( 早集合与惰性集合 | 惰性集合-序列 | generateSequence 序列创建函数 | 序列代码示例 | take 扩展函数分析 )_及早集合



2、使用序列 Sequence 实现



使用传统方式实现素数查找 , 如 : 从 1 ~ 1000 的区间内查找素数 , 必须将 1000 个元素的集合生成出来

如果使用 序列 Sequence 实现 , 则 只需要实现需要的部分 , 没有遍历的元素不会生成 ;



代码示例 :

/**
* 为 Int 定义扩展函数, 判断接收者是否是素数
*/
fun Int.isPrimeNumber(): Boolean {
// number 参数是被遍历的 接收者集合 的 受检元素
// 符合下面的要求 才会被放入新集合
// 遍历时每个 受检元素 都要 被 [2..number - 1] 区间的数值进行遍历
val isPrimeNumber = (2..this - 1)
// 计算 number 与 [2..number - 1] 区间中的数值 相除的 余数
// 也就是验证 是否 只有 1 和 其本身 可以被其整除
.map { this % it }
// 通过 map 变换计算出的余数
// 不能出现 余数 为 0 的情况
// 一旦出现 就返回 false
.none{it == 0}
return isPrimeNumber
}

fun main() {
val numbers = generateSequence(2) { it + 1 } // 设置初始值为 2 , 然后每次值自增 1
.filter { it.isPrimeNumber() } // 遍历序列元素 , 查询是否是素数
.take(20) // 取前 20 个素数

println(numbers)
}

执行结果 :

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]

【Kotlin】函数式编程 ③ ( 早集合与惰性集合 | 惰性集合-序列 | generateSequence 序列创建函数 | 序列代码示例 | take 扩展函数分析 )_kotlin_02



3、take 扩展函数分析



下面是 普通集合 调用的 take 扩展函数 原型 和 序列 Sequence 调用的 take 扩展函数

序列 Sequence 调用 take 函数时 , take 函数调用了序列的部分内容 , 决定了 序列 Sequence 的执行次数 , 生成多少元素 , 如 : 上述代码示例中 take 函数取够了 20 个素数 , 之后 Sequence 就不再继续生成后续元素了 ;



普通集合 调用的 take 扩展函数 原型 和 序列 Sequence 调用的 take 扩展函数 的对比 :

  • 普通集合 调用的 take 扩展函数 原型 :
/**
* Returns a list containing first [n] elements.
*
* @throws IllegalArgumentException if [n] is negative.
*
* @sample samples.collections.Collections.Transformations.take
*/
public fun <T> Iterable<T>.take(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
if (this is Collection<T>) {
if (n >= size) return toList()
if (n == 1) return listOf(first())
}
var count = 0
val list = ArrayList<T>(n)
for (item in this) {
list.add(item)
if (++count == n)
break
}
return list.optimizeReadOnlyList()
}
  • 序列 Sequence 调用的 take 扩展函数 原型 :
/**
* Returns a sequence containing first [n] elements.
*
* The operation is _intermediate_ and _stateless_.
*
* @throws IllegalArgumentException if [n] is negative.
*
* @sample samples.collections.Collections.Transformations.take
*/
public fun <T> Sequence<T>.take(n: Int): Sequence<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
return when {
n == 0 -> emptySequence()
this is DropTakeSequence -> this.take(n)
else -> TakeSequence(this, n)
}
}


标签:generateSequence,函数,元素,集合,take,序列
From: https://blog.51cto.com/u_14202100/6065681

相关文章

  • 默认参数、占位参数、函数重载
    (一)默认参数C++函数中的形参列表中的形参是可以有默认值的语法:返回值类型函数名(参数=默认值){}注意事项:如果我们自己传入数据,就用自己的数据,如果没有,就用默认值如果......
  • 【JS】Pug调用自定义JS函数
    当我用node.js从数据库中查询datetime类型的日期字段,并输出到网页上时,发现JS自动进行了类型转换:由2023-01-0721:47:00变成了 SatJan07202321:47:00GMT+0800......
  • 使用 Kitten 编程猫绘制一个 Y 方向平铺的立方体集合
    效果如下图所示:我们实际上使用了2D来模拟3D效果。应用程序启动时,默认只绘制一个立方体,因此我们在初始绘制的函数里,只执行动态绘制X方向的立方体这一个逻辑。因为默......
  • 【IMX6ULL学习笔记】十五、设备树DTS操作函数
    一、设备树常用OF操作函数设备树描述了设备的详细信息,这些信息包括数字类型的、字符串类型的、数组类型的,我们在编写驱动的时候需要获取到这些信息。Linux内核给我们提......
  • sql中的窗口函数
    一、简述窗口函数常用的有排序窗口函数,聚合窗口函数,使用时一般是这种格式函数名()over(PARTITIONby字段名ORDERBY字段名)二、排序窗口函数假设有这样一张员工......
  • List集合-数据结构
    List集合-数据结构数据结构是计算机存储,组织数据的方式.是指相互之间存在一种或多种特定关系的数据元素的集合.通常情况下,精心选择的数据结构可以带来更高的运行或者......
  • 九曲序列数
    问题:生成九曲序列数(1-28),1-7、15-21顺序;8-14、22-28倒序。 函数公式解决:=IF(MOD(COLUMN(A1),2),ROW(A1)-7,-ROW(A1)+1)+COLUMN(A1)*7MOD(COLUMN(A1),2)部分生成1、......
  • Map集合
    介绍 Map在Java⾥边是⼀个接⼝,常⻅的实现类有HashMap、LinkedHashMap、TreeMap和ConcurrentHashMap  内嵌类    Map是java中的接口,Map.Entry是Map的一......
  • C# List集合查找删除指定数据
    1.实体类publicclassFaultLevelModel{publicstringLBWJ{get;set;}publicstringLBSJ{get;set;}publicstringINDCODE{get;set;}}2.操作第......
  • 纯虚函数和抽象类
    纯虚函数和抽象类纯虚函数是一种特殊的虚函数,在某些情况下,基类中不能对虚函数给出有意义的实现,把它声明为纯虚函数。纯虚函数只有函数名、参数和返回值类型,没有函数体,具......