Lambda 表达式有何用处?如何使用?

答主对Java比较熟悉,就用Java来讲一讲吧。
在这里插入图片描述

什么是Lambda?

我们知道,对于一个Java变量,我们可以赋给其一个“”。
在这里插入图片描述
如果你想把“一块代码”赋给一个Java变量,应该怎么做呢?

比如,我想把右边那块代码,赋给一个叫做aBlockOfCode的Java变量:
在这里插入图片描述
在Java 8之前,这个是做不到的。但是Java 8问世之后,利用Lambda特性,就可以做到了。
在这里插入图片描述
当然,这个并不是一个很简洁的写法。所以,为了使这个赋值操作更加elegant, 我们可以移除一些没用的声明。
在这里插入图片描述
这样,我们就成功的非常优雅的把“一块代码”赋给了一个变量。而“这块代码”,或者说“这个被赋给一个变量的函数”,就是一个Lambda表达式。
但是这里仍然有一个问题,就是变量aBlockOfCode的类型应该是什么?
在Java 8里面,所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是”那段代码“,需要是这个接口的实现。这是我认为理解Lambda的一个关键所在,简而言之就是,Lambda表达式本身就是一个接口的实现。直接这样说可能还是有点让人困扰,我们继续看看例子。我们给上面的aBlockOfCode加上一个类型:
在这里插入图片描述
这种只有一个接口函数需要被实现的接口类型,我们叫它”函数式接口“。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口”,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了:
在这里插入图片描述
这样,我们就得到了一个完整的Lambda表达式声明:
在这里插入图片描述

Lambda表达式有什么作用?

最直观的作用就是使得代码变得异常简洁。
我们可以对比一下Lambda表达式和传统的Java对同一个接口的实现:
在这里插入图片描述
这两种写法本质上是等价的。但是显然,Java 8中的写法更加优雅简洁。并且,由于Lambda可以直接赋值给一个变量,我们就可以直接把Lambda作为参数传给函数, 而传统的Java必须有明确的接口实现的定义,初始化才行:
在这里插入图片描述
有些情况下,这个接口实现只需要用到一次。传统的Java 7必须要求你定义一个“污染环境”的接口实现MyInterfaceImpl,而相较之下Java 8的Lambda, 就显得干净很多。
在这里插入图片描述
Lambda结合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代码变的更加简洁!

直接上例子。
假设Person的定义和List的值都给定。
在这里插入图片描述
现在需要你打印出guiltyPersons List里面所有LastName以"Z"开头的人的FirstName。

原生态Lambda写法:定义两个函数式接口,定义一个静态函数,调用静态函数并给参数赋值Lambda表达式。
在这里插入图片描述
这个代码实际上已经比较简洁了,但是我们还可以更简洁么?
当然可以。在Java 8中有一个函数式接口的包,里面定义了大量可能用到的函数式接口(java.util.function (Java Platform SE 8 )
)。所以,我们在这里压根都不需要定义NameChecker和Executor这两个函数式接口,直接用Java 8函数式接口包里的Predicate和Consumer就可以了——因为他们这一对的接口定义和NameChecker/Executor其实是一样的。
在这里插入图片描述
第一步简化 - 利用函数式接口包:
在这里插入图片描述
静态函数里面的for each循环其实是非常碍眼的。这里可以利用Iterable自带的forEach()来替代。forEach()本身可以接受一个Consumer 参数。
第二步简化 - 用Iterable.forEach()取代foreach loop:
在这里插入图片描述
由于静态函数其实只是对List进行了一通操作,这里我们可以甩掉静态函数,直接使用stream()特性来完成。stream()的几个方法都是接受Predicate,Consumer等参数的(java.util.stream (Java Platform SE 8 )
)。你理解了上面的内容,stream()这里就非常好理解了,并不需要多做解释。
第三步简化 - 利用stream()替代静态函数:
在这里插入图片描述
对比最开始的Lambda写法,这里已经非常非常简洁了。但是如果,我们的要求变一下,变成print这个人的全部信息,及p -> System.out.println(p); 那么还可以利用Method reference来继续简化。所谓Method reference, 就是用已经写好的别的Object/Class的method来代替Lambda expression。格式如下:
在这里插入图片描述
第四步简化 - 如果是println(p),则可以利用Method reference代替forEach中的Lambda表达式:
在这里插入图片描述
这基本上就是能写的最简洁的版本了。
在这里插入图片描述

Lambda配合Optional可以使Java对于null的处理变的异常优雅

这里假设我们有一个person object,以及一个person object的Optional wrapper:
在这里插入图片描述
Optional如果不结合Lambda使用的话,并不能使原来繁琐的null check变的简单。
在这里插入图片描述
只有当Optional结合Lambda一起使用的时候,才能发挥出其真正的威力!
我们现在就来对比一下下面四种常见的null处理中,Java 8的Lambda+Optional和传统Java两者之间对于null的处理差异。
情况一 - 存在则开干
在这里插入图片描述
情况二 - 存在则返回,无则返回屁
在这里插入图片描述
情况三 - 存在则返回,无则由函数产生
在这里插入图片描述
情况四 - 夺命连环null检查
在这里插入图片描述
由上述四种情况可以清楚地看到,Optional+Lambda可以让我们少写很多ifElse块。尤其是对于情况四那种夺命连环null检查,传统java的写法显得冗长难懂,而新的Optional+Lambda则清新脱俗,清楚简洁。
在这里插入图片描述
关于Java的Lambda, 还有东西需要讨论和学习。比如如何handle lambda exception,如何利用Lambda的特性来进行parallel processing等。总之,我只是一如既往地介绍个大概,让你大概知道,哦!原来是这样子就OK了。网上关于Lambda有很多相关的教程,多看多练。假以时日,必定有所精益。

内容概要:本书《Deep Reinforcement Learning with Guaranteed Performance》探讨了基于李雅普诺夫方法的深度强化学习及其在非线性系统最优控制中的应用。书中提出了一种近似最优自适应控制方法,结合泰勒展开、神经网络、估计器设计及滑模控制思想,解决了不同场景下的跟踪控制问题。该方法不仅保证了性能指标的渐近收敛,还确保了跟踪误差的渐近收敛至零。此外,书中还涉及了执行器饱和、冗余解析等问题,并提出了新的冗余解析方法,验证了所提方法的有效性和优越性。 适合人群:研究生及以上学历的研究人员,特别是从事自适应/最优控制、机器人学和动态神经网络领域的学术界和工业界研究人员。 使用场景及目标:①研究非线性系统的最优控制问题,特别是在存在输入约束和系统动力学的情况下;②解决带有参数不确定性的线性和非线性系统的跟踪控制问题;③探索基于李雅普诺夫方法的深度强化学习在非线性系统控制中的应用;④设计和验证针对冗余机械臂的新型冗余解析方法。 其他说明:本书分为七章,每章内容相对独立,便于读者理解。书中不仅提供了理论分析,还通过实际应用(如欠驱动船舶、冗余机械臂)验证了所提方法的有效性。此外,作者鼓励读者通过仿真和实验进一步验证书中提出的理论和技术。
Lambda表达式在现代C++编程中是非常强大的工具,它的灵活性和简洁性使其适用于多种场景。以下是Lambda表达式的几个常见用途: ### 1. **作为回调函数** 许多标准库算法允许传入自定义操作,这时可以使用Lambda表达式来快速定义这些操作而无需显式声明独立函数或仿函(functor)。例如,在对容器进行排序时指定特定规则: ```cpp std::vector<int> vec = {5, 2, 9}; std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; }); // 按降序排列 ``` ### 2. **线程创建** 当你需要用新线程运行某段代码块时,可以直接在线程构造过程中传递一个lambda: ```cpp #include <thread> void someFunction() {} // 创建并启动一个新的线程执行someFunction() auto t = std::thread([]{ someFunction(); }); t.join(); ``` 这里注意资源管理和异常安全等问题。 ### 3. **数据过滤与变换** 结合STL中的`transform`, `remove_if`等算法能够高效完成批量处理任务如数组元素筛选、映射等功能。 ```cpp std::vector<int> numbers = {1, 2, 3, 4}; std::vector<int> squares; std::transform(numbers.begin(), numbers.end(), back_inserter(squares), [](int x){return x*x;}); // 计算每个数平方放入squares中 ``` ### 4. **捕捉上下文状态简化逻辑流控制结构** 利用捕获机制保存临时变量供后续步骤调用非常方便实用特别是在嵌套循环内部判断条件复杂的情况下避免过多层if else语句堆积提高可读性和维护效率 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值