
// // 第 5 课Lambda、高阶函数、集合链式、接口 // fun main() { // 一、Lambda把“一段代码”当作值 // 普通变量存的是数据(数字/字符串)lambda 让变量能存“一段可执行的逻辑”。 // 语法{ 参数 - 逻辑 } val square { x: Int - x * x } // 一个“求平方”的逻辑存进变量 println(5 的平方 ${square(5)}) // 像调用函数一样用它 // 多个参数 val plus { a: Int, b: Int - a b } println(3 4 ${plus(3, 4)}) // 二、高阶函数参数是“函数”的函数 // calc 的第三个参数 op 本身是一段逻辑调用时传不同的 lambda 就有不同效果 println(用加法${calc(10, 5, plus)}) println(用减法${calc(10, 5) { a, b - a - b }}) // 直接现写一个 lambda // repeatAction把“要做的事”作为参数传进去重复执行 repeatAction(3) { println( 滴~ 第 $it 次) } // it 是第几次 // 三、集合链式操作进阶 // 定义一批学生数据用第4课学的 data class val students listOf( Student(小明, 85, 一班), Student(小红, 92, 二班), Student(小刚, 58, 一班), Student(小美, 76, 二班), Student(小强, 88, 一班), ) // 1) 链式筛及格 - 按分数从高到低排 - 只取名字 val topNames students .filter { it.score 60 } // 及格 .sortedByDescending { it.score } // 分数降序 .map { it.name } // 变成名字列表 println(及格学生(按分数降序)$topNames) // 2) groupBy按班级分组得到 Map班级, List学生 val byClass students.groupBy { it.clazz } for ((clazz, list) in byClass) { val names list.map { it.name } println($clazz 有$names) } // 3) 常用聚合 println(平均分 ${students.map { it.score }.average()}) println(分数最高的是 ${students.maxByOrNull { it.score }?.name}) println(有没有不及格的 ${students.any { it.score 60 }}) println(是不是全都及格 ${students.all { it.score 60 }}) // 四、接口 interface定义“能力/契约” // 接口只规定“必须有哪些方法”具体怎么做由实现类决定。 // 这里让不同的“可以发声的东西”都实现 Sound 接口。 val things: ListSound listOf(Bell(), Phone()) for (t in things) { t.play() // 调用时不用管它具体是铃还是手机只要它能 play } } // 高阶函数定义 // op 的类型是 (Int, Int) - Int表示“接收两个Int、返回一个Int的函数” fun calc(a: Int, b: Int, op: (Int, Int) - Int): Int { return op(a, b) // 执行传进来的那段逻辑 } // action 的类型是 (Int) - Unit接收一个Int、不返回东西(Unit相当于void) fun repeatAction(times: Int, action: (Int) - Unit) { for (i in 1..times) { action(i) // 把当前次数传给那段逻辑 } } // data class第4课学过 data class Student(val name: String, val score: Int, val clazz: String) // 接口和它的实现 // 接口规定“凡是 Sound都必须能 play()”但不写具体实现 interface Sound { fun play() } // 两个不同的类各自实现 Sound 的 play() class Bell : Sound { override fun play() println(铃声叮铃铃~) } class Phone : Sound { override fun play() println(手机震动 来电铃声) }全部跑通 5 的平方 25用加法15 用减法5及格学生(按分数降序)[小红, 小强, 小明, 小美]一班 有[小明, 小刚, 小强]二班 有[小红, 小美]平均分 79.8 分数最高的是 小红有没有不及格的 true 是不是全都及格 false铃声叮铃铃~ 手机震动 来电铃声第 5 课知识点复盘一、Lambda把一段代码当成值普通变量存数字/字符串lambda 让你把一段逻辑存进变量、当参数传递。val square { x: Int - x * x } // { 参数 - 逻辑 }square(5) // 得到 25这是第 3 课里filter { it 60 }那个{ }的真面目——它就是个 lambda。二、高阶函数参数是函数的函数函数的参数也可以是另一段逻辑这让代码超级灵活fun calc(a: Int, b: Int, op: (Int, Int) - Int): Int op(a, b)calc(10, 5) { a, b - a - b } // 传不同 lambda 就有不同行为(Int, Int) - Int读作接收两个 Int、返回一个 Int 的函数类型小技巧如果 lambda 是最后一个参数可以把它挪到括号外面写叫尾随 lambda就像calc(10, 5) { ... }。你之前见的filter { }、for之外的很多写法都靠它。三、集合链式操作 —— 真实开发天天用 ✨把多个操作像流水线一样接起来students.filter { it.score 60 } // 筛.sortedByDescending { it.score } // 排.map { it.name } // 变换常用武器一览方法作用filter { }筛选map { }变换每个元素sortedBy / sortedByDescending排序groupBy { }分组 →MapmaxByOrNull { }找最大的那个元素any { }/all { }有没有任意一个 / 是不是全部满足sum / average / count求和/平均/计数四、接口interface—— 定义能力契约接口只规定必须有哪些方法不管具体怎么实现interface Sound { fun play() } // 契约凡是 Sound 都能 playclass Bell : Sound { override fun play() ... }class Phone : Sound { override fun play() ... }好处使用方只关心它能play()不关心它到底是铃还是手机。这叫面向接口编程是写大型可维护程序、以及 KMP 里expect/actual机制的思想基础。 接口 vs 继承继承是是一种Dog 是一种 Animal接口是能做某事Bell 能发声。一个类只能继承一个父类但可以实现多个接口。小练习 ✍️用今天学的链式操作试试可以让我帮你跑用上面的students列表找出**一班里分数最高的学生的名字**。 提示先filter出一班再maxByOrNull { it.score }最后取?.name。