Kotlin学习(4)Lambda

本文深入探讨Kotlin中的Lambda表达式的特性和用法,包括其作为对象的本质、与Java中的Lambda对比、成员引用、函数式API等内容,并通过实例展示Kotlin语言简洁而强大的特性。

记住Lambda的本质,还是一个对象。和JS,Python等不同的是,Kotlin里的Lambda不是方法,而是一个简化了的对象。

此外,Kotlin里面的没有匿名函数这一说,函数也不是传统的对象。

看看Kotlin的Lambda

//Java
button.setOnClickListener(v -> {//...})

//Kotlin
button.setOnClickListen{//...}

一个Lambda函数

it是一个lamdba隐含对象,可能是Iterable的简写吧
data class Person(val name: String, val age: Int)

fun main(vararg args: String){
    val people = listOf<Person>(
        Person("Alice",29),
        Person("Bob",31)
    )

    //使用隐含对象
    println(people.maxBy { it.age })
    //使用成员对象引用
    println(people.maxBy(Person::age))
    //类Java
    println(people.maxBy{ p: Person -> p.age})
}

Lambda句法

//Java
static IntBinaryOperator add = (x, y) -> x + y;

public static void main(String...args){
    add.applyAsInt(1,2)
}


//Kotlin
val sum = { x: Int, y: Int -> x + y }

fun main(vararg args: String){
    sum(1,2)
}
咋一看挺迷惑的,需要看看Java中的写法
因为上面说了Lambda是个对象,那么对象能像函数一样调用呐?

这里写图片描述

证实了我们的观点,确实是个对象,sum()应该是sum.invoke()的语法糖吧

直接调用Lambda

{ x: Int, y: Int -> x + y }(1,2)

//run适用于无参数的Lambda
run { print(24)}

看一个例子

transform申明要一个Lambda参数
public fun <T> Iterable<T>.joinToString(
    separator: CharSequence = ", ", 
    prefix: CharSequence = "", 
    postfix: CharSequence = "", 
    limit: Int = -1, 
    truncated: CharSequence = "...", 
    transform: ((T) -> CharSequence)? = null): String {
    return ...
}

在Lambda中使用可变变量

在Java中,Lambda中不能使用变量,如下
public static void main(String...args){
    int i = 0;
    Runnable r = () -> {
       i++;//会报错
    };
}

//只能这么做
static class I{
    public static int i = 0;
}
public static void main(String...args){
    Runnable r = () -> {
        I.i++;
    };
}
但是在Kotlin中可以
var count = 0
val inc = { count++ }

成员引用

可以视为Java反射包中的Field和Method
data class Person(val name: String, val age: Int)
Person::age//property age

fun sulate() = println("aaa")
val a = run(::salute)//function add

//构造器引用
val createPerson = ::Person
val p = createPerson("Alice", 29)

val personAgeFunction = Person::age
println(personAgeFunction(p)) //29

val thisPersonAgeFunction = p::age
println(thisPersonAgeFunction()) //29
最后两个例子可能有些疑惑,但本质personAgeFunction还是一个对象,像函数一样调用还是一个语法糖(personAgeFunction.get())

函数式API

典型的声明式编程,和SQL语句有共同之处。语义很好理解,不解释了
  • filter
  • map: map是将集合中的每个元素变成另一种A->B
  • filterKeys
  • mapKeys
  • filterValues
  • mapValues
  • all
  • any
  • count
  • find
  • groupBy
    val people = listOf<Person>(
            Person("a",19),
            Person("b",28),
            Person("c",19),
            Person("d",20)
    )

    val result = people.groupBy { it.age }
    println(result)
    println(result.javaClass)
    /*
    {19=[Person(name=a, age=19), Person(name=c, age=19)], 
    28=[Person(name=b, age=28)], 
    20=[Person(name=d, age=20)]}

    class java.util.LinkedHashMap
    */
  • flatMap: flatMap将每个元素变成一个集合再合并这些集合A->[1,2…]
  • flatten
  • toList()
  • toSet()
  • asSequence: 类似于Java8的stream()
//传统链式调用,会产生一个map的结果和一个filter的List结果
//当集合很大时,有很大的性能开销
val result = people.map { it.age }
                   .filter { it > 20 }

//改为使用asSequence(),最后别忘了加上toList()
val result = people.asSequence()
                    .map { it.age }
                    .filter { it > 20 }
                    .toList()

这里写图片描述

创建Sequence

val number = generateSequence(0) { it + 1 }
val numbersTo100 = number.takeWhile { it <= 100 }
println(numbersTo100.sum())
### KotlinLambda 表达式的用法与特性 KotlinLambda 表达式是一种匿名函数的形式,它可以让代码更加简洁和灵活。Lambda 表达式通常用于集合操作、事件回调以及其他需要传递行为的场景[^1]。 #### 1. 基本语法 Kotlin 中的 Lambda 表达式由一对大括号 `{}` 包裹,其中包含参数列表(可选)、箭头 `->` 和表达式体。以下是基本语法结构: ```kotlin { parameters -> body } ``` - **parameters**: 参数列表,可以为空。 - **body**: 表达式的主体部分,通常是执行的操作或返回的结果。 如果 Lambda 只有一个参数,则该参数可以用默认的关键字 `it` 来代替,无需显式声明[^4]。 #### 2. 示例代码 ##### (1)无参 LambdaLambda 不接收任何参数时,可以直接省略参数列表和箭头: ```kotlin val greet: () -> Unit = { println("Hello, World!") } greet() ``` 此处定义了一个名为 `greet` 的无参 Lambda,并通过调用 `greet()` 执行打印操作[^5]。 ##### (2)带参 Lambda 对于有参数的 Lambda,需明确列出参数及其类型(如果编译器无法推断)。例如: ```kotlin val sum: (Int, Int) -> Int = { x, y -> x + y } println(sum(3, 5)) // 输出:8 ``` 在此示例中,`sum` 是一个接受两个整数并返回其和的 Lambda 函数。 ##### (3)使用 `it` 关键字 当 Lambda 只有一个参数时,可以使用 `it` 自动引用这个参数,而不需要显式命名: ```kotlin val numbers = listOf(1, 2, 3, 4) numbers.forEach { println(it * 2) } // 将每个元素乘以 2 并打印 ``` 这里的 `forEach` 方法会依次将列表中的每一个元素传入 Lambda,自动绑定到 `it` 上[^4]。 ##### (4)自调用 Lambda Lambda 还可以在定义的同时立即执行,称为自调用 Lambda: ```kotlin {x: Int, y: Int -> x + y}(3, 5) // 结果为 8 ``` 这种形式允许我们在不存储 Lambda 的情况下直接运行它。 #### 3. 作为参数传递给函数 Lambda 经常用作高阶函数的参数。所谓高阶函数是指那些可以接收函数作为参数或将函数作为返回值的函数。例如: ```kotlin fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int { return operation(a, b) } val result = operate(10, 5) { x, y -> x - y } println(result) // 输出:5 ``` 在这个例子中,`operate` 接收三个参数,最后一个是一个 Lambda 表达式,用来定义具体的运算逻辑。 #### 4. 类型推断 Kotlin 编译器可以根据上下文环境推断出 Lambda 的类型,因此很多时候我们不必手动指定类型。例如: ```kotlin listOf(1, 2, 3).filter { it % 2 == 0 } // 筛选出偶数 ``` 这里 `filter` 方法期望的是一个 `(T) -> Boolean` 形式的 Lambda,但由于上下文清晰,我们可以省去显式类型声明[^3]。 --- ### 总结 KotlinLambda 表达式提供了一种优雅的方式来编写简洁且高效的代码。无论是处理集合数据还是构建复杂的业务逻辑,Lambda 都能显著提升开发效率和代码可读性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值