Kotlin学习笔记(9)--Lambda 表达式与高阶函数

Lambda 表达式与高阶函数

在 Kotlin 中,Lambda 表达式高阶函数是函数式编程的重要组成部分,它们使代码更加简洁、灵活和可复用。以下将详细介绍这两个概念及其使用方法。

Lambda 表达式

Lambda 表达式是一种简洁的方式来表示可以传递的匿名函数。Lambda 表达式的基本语法如下:

{ 参数列表 -> 函数体 }
  • 参数列表:参数与类型,类似于普通函数的参数。
  • ->:箭头符号,用于分隔参数列表和函数体。
  • 函数体:执行的代码块,最后一行表达式的值就是 Lambda 的返回值。

示例

// 定义一个 Lambda 表达式,计算两个整数的和
val sum = { a: Int, b: Int -> a + b }
println(sum(3, 4)) // 输出 7

// 没有参数的 Lambda 表达式
val greet = { println("Hello, Kotlin!") }
greet() // 输出 "Hello, Kotlin!"

简化语法

如果 Lambda 表达式的参数类型可以被推断,或者只有一个参数,可以进一步简化语法:

// 单一参数,可以使用 'it' 作为默认参数名
val square: (Int) -> Int = { it * it }
println(square(5)) // 输出 25

// 多个参数,类型可以被推断
val multiply = { a: Int, b: Int -> a * b }
println(multiply(3, 4)) // 输出 12

Lambda 表达式的类型推导

在很多情况下,Kotlin 可以根据上下文推断出 Lambda 表达式的参数类型和返回类型,因此可以简化 Lambda 表达式的书写。

// 在高阶函数中使用 Lambda 表达式,类型可以省略
listOf(1, 2, 3, 4, 5).filter { it > 2 }.forEach { println(it) }
// 输出:
// 3
// 4
// 5

在上面的例子中,it 是 Lambda 表达式的隐式参数,表示当前元素。如果不简化,则如下方式书写。

// 在高阶函数中使用 Lambda 表达式,类型可以省略
listOf(1, 2, 3, 4, 5).filter { it -> it > 2 }.forEach { println(it) }
// 输出:
// 3
// 4
// 5

高阶函数

高阶函数是指可以接受一个或多个函数作为参数,或者返回一个函数的函数。高阶函数允许我们将函数作为第一类公民来使用,极大地提高了代码的灵活性和可复用性。

高阶函数的定义

Kotlin 中定义高阶函数的语法如下:

kotlin
fun functionName(parameter: Type, lambda: (ParamType) -> ReturnType): ReturnType {
    // 函数体
}

示例:传递 Lambda 作为参数

// 定义一个高阶函数,接受两个整数和一个操作函数
fun operateFunc(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

fun main() {
    val sum = operateFunc(5, 3) { x, y -> x + y }
    println(sum) // 输出 8

    val product = operateFunc(5, 3) { x, y -> x * y }
    println(product) // 输出 15
}

// 定义一个高阶函数,接受一个整数列表和一个函数作为参数
fun operateOnList(numbers: List<Int>, operation: (Int) -> Int): List<Int> {
    val result = mutableListOf<Int>()
    for (number in numbers) {
        result.add(operation(number))
    }
    return result
}

// 使用高阶函数,传入一个 Lambda 表达式来对列表中的每个元素进行平方操作
val numbers = listOf(1, 2, 3, 4, 5)
val squared = operateOnList(numbers) { it * it }
println(squared) // 输出: [1, 4, 9, 16, 25]

// 另一个示例,传入一个 Lambda 表达式来对列表中的每个元素进行加倍操作
val doubled = operateOnList(numbers) { it * 2 }
println(doubled) // 输出: [2, 4, 6, 8, 10]

使用标准库的高阶函数

Kotlin 标准库提供了许多常用的高阶函数,如 map, filter, reduce, forEach 等,这些函数极大地简化了集合操作。

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)

    // 使用 map 将每个元素乘以 2
    val doubled = numbers.map { it * 2 } // numbers.map { it -> it * 2 } 的缩写。
    println(doubled) // 输出 [2, 4, 6, 8, 10]

    // 使用 filter 过滤出偶数
    val evens = numbers.filter { it % 2 == 0 }
    println(evens) // 输出 [2, 4]

    // 使用 forEach 打印每个元素
    numbers.forEach { println(it) }
    /*
        输出:
        1
        2
        3
        4
        5
    */
}

自定义高阶函数

根据需要定义自己的高阶函数,以实现更复杂的逻辑。

示例:自定义计数函数

fun main() {
    val fruits = listOf("apple", "banana", "cherry", "date")

    // 使用自定义高阶函数计算长度为 6 的字符串数量
    val count = fruits.customCount { it.length == 6 }
    println(count) // 输出 2
}

// 定义一个扩展高阶函数,接受一个条件函数作为参数
fun List<String>.customCount(condition: (String) -> Boolean): Int {
    var counter = 0
    for (item in this) {
        if (condition(item)) {
            counter++
        }
    }
    return counter
}

函数类型与类型推断

在 Kotlin 中,函数本身也是一种类型,可以作为变量的类型或函数的参数类型。

示例:函数类型作为变量

// 定义一个函数类型的变量
val printMessage: (String) -> Unit = { message -> println(message) }
printMessage("Hello from lambda!") // 输出 "Hello from lambda!"

// 另一种方式,使用函数引用
fun display(message: String) {
    println(message)
}

val printMessageRef: (String) -> Unit = ::display
printMessageRef("Hello from function reference!") // 输出 "Hello from function reference!"

高阶函数与返回值

高阶函数不仅可以接受函数作为参数,还可以返回一个函数。

示例:返回函数的高阶函数

// 定义一个高阶函数,返回一个根据因子倍增的函数
fun getMultiplier(factor: Int): (Int) -> Int {
    return { number -> number * factor }
}

fun main() {
    val double = getMultiplier(2) // 返回一个高阶函数
    val triple = getMultiplier(3)

    println(double(5)) // 输出 10
    println(triple(5)) // 输出 15
}

函数引用

Kotlin 允许使用已有的函数作为高阶函数的参数,这通过函数引用实现,使用 :: 语法。

示例:使用函数引用

// 定义一个普通函数
fun isEven(number: Int): Boolean {
    return number % 2 == 0
}

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5, 6)

    // 使用函数引用作为 filter 的参数
    val evens = numbers.filter(::isEven)
    println(evens) // 输出 [2, 4, 6]
}

匿名函数与 Lambda 的区别

虽然 Lambda 表达式和匿名函数都可以用于高阶函数,但它们在某些情况下有细微的区别:

  • 返回类型:匿名函数可以明确指定返回类型,而 Lambda 依赖类型推断。
  • 标签:匿名函数可以使用 return 语句返回到调用它的函数,而 Lambda 中的 return 只会退出 Lambda 本身。

示例

fun main() {
    val lambda = { x: Int -> x * x }
    println(lambda(4)) // 输出 16

    val anonymous = fun(x: Int): Int {
        return x * x
    }
    println(anonymous(4)) // 输出 16
}
posted @ 2024-10-19 19:21  Jacob-Chen  阅读(50)  评论(0)    收藏  举报