Kotlin中匿名函数(又称为Lambda,或者闭包)和高阶函数的详解

简介: Kotlin中匿名函数(又称为Lambda,或者闭包)和高阶函数的详解

1、匿名函数

fun main() {
    /**
     * 匿名函数:
     * 1.定义时不取名字的函数,我们称之为匿名函数,匿名函数通常整体传递给其他函数,或者从其他函数返回。
     * 2.匿名函数对Kotlin来说很重要,有了它,我们能够根据需要制定特殊的规则,轻松定制标准库里的内置函数
     */
    val total = "Mississippi".count()
    println(total)
    var totals = "Mississippi".count({ letter ->
        letter == 's'
    })
    println(totals)
    /**
     * 函数类型与隐式返回
     * 1.匿名函数也有类型,匿名函数可以当作变量赋值给函数类型变量,就像其他变量一样,
     * 匿名函数就可以在代码里传递了。
     * 变量有类型,变量可以等于函数,函数也会有类型。函数的类型,由传入的参数和返回值类型决定。
     * 2.和具名函数一样,除了极少数情况外,匿名函数不需要return关键字来返回数据,匿名函数会隐式或自动返回函数体最后一行语句的结果。
     */
    //变量的类型是一个匿名函数
    val blessingFunction: () -> String
    blessingFunction = {
        val holiday = "2023"
        "Happy $holiday"
    }
    println(blessingFunction())
    val share: () -> String = {
        val story = "励志的故事"
        "分享$story"
    }
    println(share())
    val max: () -> Int = {
        val number1 = 10
        val number2 = 20
        Math.max(number1, number2)
    }
    println(max())
    /**
     * 函数参数:
     * 和具名参数一样,匿名函数可以不带参数,也可以带一个或多个任何类型的参数,需要带参数时,
     * 参数的类型放在匿名函数的类型定义中,参数名则放在函数定义中。
     */
    val enjoy: (String) -> String = { name ->
        "享受$name"
    }
    println(enjoy("编程"))
    /**
     * it关键字:
     * 定义只有一个参数的匿名函数时,可以使用it关键字来表示参数名。
     * 当你需要传入两个值参,it关键字就不能用了。
     */
    val testIt: (String) -> String = {
        "$it 使用it参数"
    }
    println(testIt("测试"))
    /**
     * 类型推断一
     * 1.定义一个变量时,如果把匿名函数作为变量赋值给它,就不需要显示指明变量类型了。
     */
    val studyKotlin = {
        val content = "kotlin"
        "study $content"
    }
    println(studyKotlin())
    val today = {
        val date = 15
        date + 5
    }
    println("今天${today()}日")
    /**
     * 类型推断二
     * 类型推断也支持带参数的匿名函数,但为了帮助编译器更准确地推断变量类型,匿名函数的参数名和参数类型必须有。
     */
    val studyTime: (String, Int) -> String = { content, time ->
        val start = "今天"
        "$start 学习 $content 在 $time 月"
    }
    println(studyTime("kotlin", 1))
    val studyTime1 = { content: String, time: Int ->
        val start = "今天"
        "$start 学习 $content 在 $time 月"
    }
    println(studyTime1("Android", 1))
}

输出结果如下:

11
4
Happy 2023
分享励志的故事
20
享受编程
测试 使用it参数
study kotlin
今天20日
今天 学习 kotlin 在 1 月
今天 学习 Android 在 1 月

2、Lambda的概述

3、函数的参数是另一个函数

fun main() {
    /**
     * 定义参数是函数的函数
     * 函数的参数是另外一个函数
     */
    val getDiscountWord = { goodsName: String, hour: Int ->
        val currentYear = 2023
        "${currentYear}年,双十一${goodsName}促销倒计时:${hour}小时"
    }
    showOnBoard("卫生纸", getDiscountWord)
    var totals = "Mississippi".count({ letter ->
        letter == 's'
    })
    /**
     * 简略写法
     * 如果一个函数的Lambda参数排在最后,或者是唯一的参数,那么括住Lambda值参的一对圆括号就可以省略。
     */
    val totalBrief = "Mississippi".count { letter ->
        letter == 's'
    }
    println(totalBrief)
    val totalBriefs = "Mississippi".count {
        it == 's'
    }
    println(totalBriefs)
}
private fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String) {
    val hour = (1..24).shuffled().last()
    println(getDiscountWords(goodsName, hour))
}

输出结果如下:

2023年,双十一卫生纸促销倒计时:20小时
4
4

4、简略写法

/**
     * 简略写法
     * 如果一个函数的Lambda参数排在最后,或者是唯一的参数,那么括住Lambda值参的一对圆括号就可以省略。
     */
fun main() {
    showOnBoard("卫生纸") { goodsName: String, hour: Int ->
        val currentYear = 2023
        "${currentYear}年,双十一${goodsName}促销倒计时:${hour}小时"
    }
}
private fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String) {
    val hour = (1..24).shuffled().last()
    println(getDiscountWords(goodsName, hour))
}

输出结果如下:

2023年,双十一卫生纸促销倒计时:18小时

5、函数内联

fun main() {
    val getDiscountWords = { goodsName: String, hour: Int ->
        val currentYear = 2023
        "${currentYear}年,双十一${goodsName}促销倒计时:$hour 小时"
    }
    showOnBoard("卫生纸", getDiscountWords)
}
//内联函数
/**
 * 1、lambda可以让你更灵活地编写应用,但是,灵活也是要付出代价的。
 * 2、在JVM上,你定义的lambda会以对象实例的形式存在,JVM会为所有同lambda打交道的变量分配内存,这就产生了内存消耗。
 * 更糟的是,lambda的内存开销会带来严重的性能问题。
 * 幸运的是,kotlin有一种优化机制叫做内联,有了内联,JVM就不需要使用lambda对象实例了,因而避免了变量内存分配。哪里需要
 * 使用lambda,编译器就会将函数体复制到哪里。
 * 3、使用lambda的递归函数无法内联,因为会导致复制粘贴无限循环,编译会发出警告。
 */
private inline fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String) {
    val hour = (1..24).shuffled().last()
    println(getDiscountWords(goodsName, hour))
}

输出结果如下:

2023年,双十一卫生纸促销倒计时:17 小时

6、函数引用

fun main() {
    /**
     * 函数引用:
     * 要把函数作为参数传给其他函数使用,除了传lambda表达式,kotlin还提供了其他方法
     * 传递函数引用,函数引用可以把一个具名函数转换成一个值参,使用lambda表达式的地方
     * 都可以使用函数引用。
     */
    showOnBoard("牙膏", ::getDiscountWords)
}
private fun getDiscountWords(goodsName: String, hour: Int): String {
    val currentYear = 2023
    return "${currentYear}年,双十一${goodsName}促销倒计时:$hour 小时"
}
private fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String) {
    val hour = (1..24).shuffled().last()
    println(getDiscountWords(goodsName, hour))
}

7、函数类型作为返回值类型、以及闭包

fun main() {
    /**
     * 函数类型也是有效的返回类型,也就是说可以定义一个能返回函数的函数
     */
    var getConfigDiscountWords = configDiscountWords()
    println(getConfigDiscountWords("沐浴露"))
}
/**
 * 闭包:
 * 1.在kotlin中,匿名函数能够修改并引用定义在自己的作用域之外的变量,
 * 匿名函数引用着定义自身的函数里的变量,kotlin中的lambda就是闭包。
 * 2.能接收函数或者返回函数的函数又叫做高级函数,高级函数广泛应用于函数式编程当中。
 *
 * 重点:闭包,lambda表达式,匿名函数,三者只是叫法不同。
 */
fun configDiscountWords(): (String) -> String {
    val currentYear = 2023
    var hour = (1..24).shuffled().last()
    return { goodsName: String ->
        "${currentYear}年,双十一${goodsName}促销倒计时:$hour 小时"
    }
}

8、lambda表达式与匿名内部类

对比可以看出kotlin的简洁性,同样的逻辑

1、java代码

public class JavaAnonymousClass {
    public static void main(String[] args) {
        /**
         * lambda与匿名内部类
         * 为什么要在代码中使用函数类型?
         * 1.函数类型能让开发者少写模式化代码,写出更灵活的代码
         * 2.Java8支持面向对象编程和lambda表达式,但不支持将函数作为参数传递给另一个函数或者参数,
         * 不过Java的替代方案是匿名内部类。
         */
        showOnBoard("手机", new DiscountWords() {
            @Override
            public String getDiscountWords(String goodsName, int hour) {
                int currentYear = 2027;
                return String.format("%d年,双十一%s促销倒计时:%d小时", currentYear, goodsName, hour);
            }
        });
    }
    public interface DiscountWords {
        String getDiscountWords(String goodsName, int hour);
    }
    public static void showOnBoard(String goodsName, DiscountWords discountWords) {
        int hour = new Random().nextInt(24);
        System.out.println(discountWords.getDiscountWords(goodsName, hour));
    }
}

2、kotlin代码

fun main() {
    showOnBoard("卫生纸") { goodsName: String, hour: Int ->
        val currentYear = 2023
        "${currentYear}年,双十一${goodsName}促销倒计时:$hour 小时"
    }
}
private fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String) {
    val hour = (1..24).shuffled().last()
    println(getDiscountWords(goodsName, hour))
}


目录
相关文章
|
9月前
|
安全 Java 编译器
Kotlin 学习笔记(一)—— 基本类型、函数、lambda、类与对象的写法
Kotlin 作为 Android 开发的首选语言,其基础语法和特性需要重点学习。本文概括总结了 Kotlin 的基本类型、关键字、函数、闭包、高阶函数、类与对象等核心知识点,并给出示例代码进行讲解。
154 0
Kotlin 学习笔记(一)—— 基本类型、函数、lambda、类与对象的写法
|
12月前
|
安全 IDE JavaScript
From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了
Kotlin 是什么? 可以做什么? Android 官方开发语言从Java变为Kotlin,Java 有哪些问题? Kotlin的优点 Kotlin 特性(Features)
11544 1
From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了
|
Serverless Kotlin
Kotlin | 高阶函数reduce()、fold()详解
在 `Kotlin` 中,`reduce()` 和 `fold()` 是函数式编程中常用的高阶函数。它们都是对集合中的元素进行聚合操作的函数,将一个集合中的元素缩减成一个单独的值。它们的使用方式非常相似,但是返回值略有不同
112 0
|
Java 开发者 Kotlin
Kotlin中lambda表达式详解
lambda运算时java后面版本引进的,所以实现的仅仅是从形式上简化代码,内部的优化并不是非常出色,而Kotlin一开始就支持函数式编程,使得其lambda表达式具有性能上的优势,同时Kotlin简洁的风格也给lambda表达式进一步简化提供了一个良好的实现方式,下面带大家具体看看他们之间的区别以及如何更好的使用Kotlin的极简化lambda表达式
135 0
Kotlin中lambda表达式详解
|
算法 Java 编译器
Kotlin学历之函数与Lambda表达式
Kotlin学历之函数与Lambda表达式
80 0
|
Java API Kotlin
聊聊Kotlin中的lambda
聊聊Kotlin中的lambda
120 0
|
Java Android开发 图形学
Android修行手册之Kotlin-【类型转换】、【函数定义】、【匿名函数】、【可变参数】篇
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
506 0
|
Java Kotlin
【Kotlin】Lambda 表达式 ( 简介 | 表达式语法 | 表达式类型 | 表达式返回值 | 调用方式 | 完整示例 )
【Kotlin】Lambda 表达式 ( 简介 | 表达式语法 | 表达式类型 | 表达式返回值 | 调用方式 | 完整示例 )
261 0
【Kotlin】Lambda 表达式 ( 简介 | 表达式语法 | 表达式类型 | 表达式返回值 | 调用方式 | 完整示例 )
|
Java C++ Kotlin
【Kotlin】Kotlin 高阶函数 ( 高阶函数当做参数 | 高阶函数定义 | 高阶函数调用 )
【Kotlin】Kotlin 高阶函数 ( 高阶函数当做参数 | 高阶函数定义 | 高阶函数调用 )
122 0
|
Kotlin
Kotlin常用的高阶函数(Filter、TakeWhile、Let、Apply、With......)
一、Filter package net.println.kotlin.chapter5.builtins /** * @author:wangdong * @description:Kotlin常见的高阶函数 */ fun main(args: Array) { //求(0.
2581 0