常用高阶函数

xiaoxiao2025-10-24  10

Kotlin提供了不少高级语法特性。不过这些函数对于新手来说比较难于读懂,因为很多情况下,我们总会结合着lambda语法来使用。在Kotlin中的源码标准库(Standard.kt)中提供了一些Kotlin扩展的内置函数可以优化kotlin的编码。

常用高阶函数:

filter{}:过滤函数。takeWhile{}:按照顺序取数,遇到不符合要求的,就停止。let{}:调用某对象的let函数,则该对象为函数的参数,在函数块内可以通过it指代该对象。let函数另一个作用就是可以避免写一些判断null的操作。返回值为函数块的最后一行或指定return表达式。apply{}:可以直接调用对象的成员变量(方法)。返回值为调用对象自己。apply函数可以和let配合使用,更方便。with(){}:以参数的形式传入,并可直接调用对象的成员变量(方法),无需像let函数一样需要使用it来指代对象。run{}:run函数实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式。适用于let,with函数任何场景。因为run函数是let,with两个函数结合体,准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理。also{}:调用某对象的also函数,则该对象为函数的参数。在函数块内可以通过 it 指代该对象。返回值为该对象自己。also函数的结构实际上和let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。而also函数返回的则是传入对象的本身。一般可用于多个扩展函数链式调用。use{}:通常用于IO操作。即需要关闭资源的操作,使用use函数,能够自动关闭。作用域内可用it指代对象。

it和this的指代:

let、also、use都会使用it指代当前对象。with、run、apply都会使用this指代当前对象或者直接省略。

返回值

let、with、run均以闭包形式返回。apply、also均返回对象自己。

使用场景:

let:适用于处理不为null的操作场景。with:适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上。run:适用于let,with函数任何场景。also:适用于let函数的任何场景,一般可用于多个扩展函数链式调用apply:适用于run函数的任何场景,一般用于初始化一个对象实例的时候,操作对象属性,并最终返回这个对象。动态inflate出一个XML的View的时候需要给View绑定数据也会用到。一般可用于多个扩展函数链式调用。数据model多层级包裹判空处理的问题。

使用示例:

fun main(args: Array<String>) { // testFilter() // testLet() // testApply() // testApplyAndLet() // testWith() // testRun() // testAlso() // testReadFile() // testUse() } fun testFilter() { //求0~6的阶乘 (0..6).map(::factorial).forEach(::println)//map函数是对Array的扩展,是将List<T>转换成 List<R>集合 //只保留阶乘是期奇数的 println((0..6).map(::factorial).filter { it % 2 == 1 })//[1, 1] //要处于奇数位上的阶乘 println((0..6).map(::factorial).filterIndexed { index, i -> index % 2 == 1 })//[1, 6, 120] } fun testTakeWhile() { //根据条件按照顺序取数,遇到不符合要求的,就停止 println((0..6).map(::factorial).takeWhile { it % 2 == 1 }) } //阶乘公式 n!=1×2×3×...(n-1)×n private fun factorial(n: Int): Int { if (n == 0) return 1//0的阶乘为1 return (1..n).reduce { acc, total -> acc * total } } fun testLet() { val r = findTest()?.let { it.aa() println(it.a) 1 + 1 } println(r)//输出2 } fun testApply() { val r = findTest()?.apply { // 可以使用Test中的成员变量和方法 aa() println(a) } println(r?.b)//apply函数返回调用对象本身(即,Test类的对象),因此可以直接调用其成员变量b } fun testApplyAndLet() { // apply和let一起使用 findTest()?.apply { aa() println(a) findCeShi()?.let { it.cc() it.c //这里的this是指代调用apply函数的对象 println(this.b) } }?.bb()//由于apply返回的事对象自己,因此,此处可以直接调用对象的成员方法或变量 } fun testWith() { //对象作为with函数的参数 val r = with(findTest()) { println(this?.a) this?.aa() //返回值为函数块的最后一行或指定return表达式。 this?.b } println(r)//输出 b参数 } fun testRun() { val r = findTest()?.run { println(a) aa() b } println(r)//输出 b参数 } fun testAlso() { findTest()?.also { it.a it.aa() it.b }?.bb()//also函数返回调用对象本身(即,Test类的对象),因此可以直接调用其成员变量b } //普通读取文件 fun testReadFile() { val file = File("E:\\blog-note\\test.txt") //把文件内容读取进缓冲读取器 val bufferedReader = BufferedReader(FileReader(file)) var line: String while (true) { //当有内容时读取一行数据,否则退出循环 line = bufferedReader.readLine() ?: break println(line) } bufferedReader.close()//关闭缓冲读取器 } //使用use函数读取文件,操作结果与上面有一种是一致的。 fun testUse() { val file = File("E:\\blog-note\\test.txt") //把文件内容读取进缓冲读取器(use方法会自动对BufferedReader进行关闭) BufferedReader(FileReader(file)).use { var line: String while (true) { line = it.readLine() ?: break println(line) } } } fun findTest(): Test? { return Test("a参数", "b参数") } data class Test(var a: String, var b: String) { fun aa() { println("aa is exe!") } fun bb() { println("bb is exe!") } } fun findCeShi(): CeShi? { return CeShi("c参数", "d参数") } data class CeShi(var c: String, var d: String) { fun cc() { println("cc is exe!") } }
转载请注明原文地址: https://www.6miu.com/read-5038469.html

最新回复(0)