Capturing versus non-capturing lambdas 捕获和非捕获的Lambda表达式

Capturing versus non-capturing lambdas

Lambdas are said to be "capturing" if they access a non-static variable or object that was defined outside of the lambda body. For example, this lambda captures the variablex:

int x = 5; return y -> x + y;

In order for this lambda declaration to be valid, the variables it captures must be "effectively final". So, either they must be marked with thefinalmodifier, or they must not be modified after they‘re assigned.

Whether a lambda is capturing or not has implications for performance. A non-capturing lambda is generally going to be more efficient than a capturing one. Although this is not defined in any specifications (as far as I know),
and you shouldn‘t count on it for a program‘s correctness, a non-capturing lambda only needs to be evaluated once. From then on, it will return an identical instance. Capturing lambdas need to be evaluated every time they‘re encountered, and currently that performs much like instantiating a new instance of an anonymous
class.

捕获和非捕获的Lambda表达式

当Lambda表达式访问一个定义在Lambda表达式体外的非静态变量或者对象时,这个Lambda表达式称为“捕获的”。比如,下面这个lambda表达式捕捉了变量x:

int x = 5; return y -> x + y;

为了保证这个lambda表达式声明是正确的,被它捕获的变量必须是“有效final”的。所以要么它们需要用final修饰符号标记,要么保证它们在赋值后不能被改变。

Lambda表达式是否是捕获的和性能悄然相关。一个非不捕获的lambda通常比捕获的更高效,虽然这一点没有书面的规范说明(据我所知),而且也不能为了程序的正确性指望它做什么,非捕获的lambda只需要计算一次.
然后每次使用到它都会返回一个唯一的实例。而捕获的lambda表达式每次使用时都需要重新计算一次,而且从目前实现来看,它很像实例化一个匿名内部类的实例。

Lambda的性能

Oracle公司 性能比较的文档: JDK 8: Lambda Performance study, 详细而全面的比较了lambda表达式和匿名函数之间的性能差别。

lambda开发组也有一篇ppt, 其中也讲到了lambda的性能(包括capture和非capture的情况)。 lambda最差的情况性能内部类一样, 好的情况肯定比内部类性能高。

Java 8 Lambdas - they are fast, very fast

Java 8 Lambda Performance Comparison

https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started 上面也有一段关于这方面的提示:

This would create a capturing lambda, meaning that it would need to instantiate an object to hold theByteBuffer bb variable as it passes the lambda through to the
publishEvent() call. This will create additional (unnecessary) garbage, so the call that passes the argument through to the lambda should be preferred if low GC pressure is a requirement.

Give that method references can be used instead of anonymous lamdbas it is possible to rewrite the example in this fashion.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-30 06:33:27

Capturing versus non-capturing lambdas 捕获和非捕获的Lambda表达式的相关文章

正则表达式中的捕获和非捕获

之前我们在做例子的时候,我们看到过这种捕获的形式,我们也试过反向引用.那像我们捕获的内容,可以通过一个正则表达式的模式,或者部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储.缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式.每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数.当然,如果我们不想捕获我们的文本,可以使用非捕获元字符 '?:'.'?=' 或 '?!' 来重写捕获

正则数量词及非捕获

一.数量词:Greedy Reluctant Possessive         String str = "abcdabg"; // ①Greedy // output:abcdab Pattern pattern1 = Pattern.compile(".*ab"); Matcher matcher1 = pattern1.matcher(str); while (matcher1.find()) { System.out.print(matcher1.gro

JavaScript正则表达式-非捕获性分组

非捕获性分组定义子表达式可以作为整体被修饰但是子表达式匹配结果不会被存储. 非捕获性分组通过将子表达式放在"?:"符号后. str = "img1.jpg,img2.jpg,img3.bmp"; reg = /(?:\w*)(?=\.gif)/; arr_m = str.match(reg);//arr_m = ["img1","img2"]

正则表达式 非捕获性分组

非捕获性分组语法为(?:pattern),即将pattern部分组合成一个可统一操作的组合项,但不把这部分内容当作子匹配捕获,匹配的内容部进行编号也不存储在缓冲区中供以后使用.非捕获性分组方法在必须进行组合.但又不想对组合的部分进行缓存的情况下非常有用. 例如,要在一篇英文资料中查找"program"和"project"两个单词,正则表达式可表示为/program|project/,也可表示为/pro(gram|ject)/,但是缓存子匹配(gramject)没有意

正则表达式 1. 分组提取/非捕获组

https://www.zybuluo.com/Zjmainstay/note/709093 1. 分组提取/非捕获组 分组,是正则里一个非常重要的概念,我们需要针对某个区域提取数据,往往需要依赖分组.而分组,其实就是正则里()括住的部分. (1.1)分组提取 需求:在分组1中匹配meta中author属性的值源串:<meta author="Zjmainstay" />another author="Zjmainstay too"预期:分组1得到Zjm

php 正则表达式捕获组与非捕获组

熟练掌握正则表达式是每个程序员的基础要求,对于每个初学者来说会被正则表达式一连串字符弄得头晕眼花.博主便会如此,一直对正则表达式有种莫名的恐惧.近来看到另一位博友写的 <php正则表达式>一文获益良多,对其通配符以及捕获数据两个章节颇感兴趣.这两个章节正好涉及到的是正则表达式的捕获组与非捕获组的知识,因而本文来细细探讨下这部分知识. 我们知道,在正则表达式下(x) 表示匹配'x'并记录匹配的值.这只是比较通俗的说法,甚至说这是不严谨的说法,只有()捕获组形式才会记录匹配的值.非捕获组则只匹配,

Python中正则匹配使用findall,捕获分组(xxx)和非捕获分组(?:xxx)的差异

转自:https://blog.csdn.net/qq_42739440/article/details/81117919 下面是我在用findall匹配字符串时遇到的一个坑,分享出来供大家跳坑. 例题: 如图所示: 正则a和正则b两个式子匹配出来的结果是不同的. 那 ?: 的作用就是把捕获分组转变为非捕获分组. 什么是捕获组和非捕获组呢? (qq|163|126) ---> 这样单独的括号就为捕获组 (?:qq|163|126) ---> 这样在原有分组里加上?: 就把捕获组转变为一个非捕获

正则表达式分组捕获非捕获的示例理解

举几个例子 一.使用捕获型() 比如0.23 1.(^\d+)(\.)(\d{0,2}) 正则表达式有3个()使用match就会产生3个分组 2.^\d+\.\d{0,2} 没有(),不产生分组 二.非捕获型(?:) (?:^\d+)(\.)(\d{0,2}) 第一个分组不再捕获 原文地址:https://www.cnblogs.com/zhaogaojian/p/12207959.html

[012]泛型--lambda表达式捕获

lambda表达式的捕获跟参数差不多,可以是值或者引用. 1.值捕获 与传值参数类似,采用值捕获的前期是变量可以拷贝:与参数不通透的是:被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝. void func(){ int v1 = 1; auto f = [v1] { return v1;}; v1 = 0; auto j = f(); //j为1:f保存了我们创建它时v1的拷贝 } 2.引用捕获 在使用引用捕获的时候,由于lambda保存的是引用,因此值会随着引用变化而变化. vo