解问 lambda表达式
目录
1.0 何为Lambda
1.1 Lambda语法特征
1.2 Lambda实例
1.3 Lambda中的stream
1.4 Lambda 中的 stream 效率
1.0 何为Lambda
所谓 “Lambda 表达式”(lambda expression)它是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。如果想深入可以去这位仁兄的博客看看 点我进去 这里做个了解。
1.1 Lambda语法特征
认准 " - > " Lambad 老字号
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); //编译会出错
1.2 Lambda实例
从语法特征分析出的傻白甜代码片段
// 1. 不需要参数,返回值为 5
() -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x // 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y // 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
public class Java8Tester {
public static void main(String args[]){
Java8Tester tester = new Java8Tester();
// 类型声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; };
// 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
}
interface MathOperation {
int operation(int a, int b);
}
interface GreetingService {
void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
}
}
Lambda表达式应用场景
使用 ( ) - { } 来代替匿名类 代码来自这位仁兄 点我进去
//未使用Lambda
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("no use lambda");
}
});
//使用之后
Thread t2 = new Thread(() -> System.out.println("use lambda"));
我们看到相对而言Lambda表达式要比匿名类要优雅简洁很多~。
以流水线的方式处理数据
List<Integer> integers = Arrays.asList(4, 5, 6,1, 2, 3,7, 8,8,9,10); List<Integer> evens = integers.stream().filter(i -> i % 2 == 0)
.collect(Collectors.toList()); //过滤出偶数列表 [4,6,8,8,10]<br>
List<Integer> sortIntegers = integers.stream().sorted()
.limit(5).collect(Collectors.toList());//排序并且提取出前5个元素 [1,2,3,4,5] List<Integer> squareList = integers.stream().map(i -> i * i).collect(Collectors.toList());//转成平方列表 int sum = integers.stream().mapToInt(Integer::intValue).sum();//求和 Set<Integer> integersSet = integers.stream().collect(Collectors.toSet());//转成其它数据结构比如set Map<Boolean, List<Integer>> listMap = integers.stream().collect(Collectors.groupingBy(i -> i % 2 == 0)); //根据奇偶性分组 List<Integer> list = integers.stream().filter(i -> i % 2 == 0).map(i -> i * i).distinct().collect(Collectors.toList());//复合操作
1.3 Lambda表达式中的Stream
在java 8 中 Stream 不是集合元素,它不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。
Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。而和迭代器又不同的是,Stream 可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个 item 读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream 的并行操作依赖于 Java7 中引入的 Fork/Join 框架(JSR166y)来拆分任务和加速处理过程。
甚至函数 由值创建流:
Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");
由数组创建流:
int[] numbers = {2, 3, 5, 7, 11, 13}; int sum = Arrays.stream(numbers).sum();
用内部迭代取代外部迭代
外部迭代:描述怎么干,代码里嵌套2个以上的for循环的都比较难读懂;只能顺序处理List中的元素;
内部迭代:描述要干什么,而不是怎么干;不一定需要顺序处理List中的元素
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String feature : features) {
System.out.println(feature); //外部迭代
}
List features = Arrays.asList("Lambdas", "Default Method", "Stream API",
"Date and Time API");
features.stream.forEach(n -> System.out.println(n)); //内部迭代
1.4 Lambda 中的 stream 效率
Lambda的并行流虽好,但也要注意使用场景。如果平常的业务处理比如过滤,提取数据,没有涉及特别大的数据和耗时操作,则真的不需要开启并行流。我在工作中看到有些人一个只有几十个元素的列表的过滤操作也开启了并行流,其实这样做会更慢。因为多行线程的开启和同步这些花费的时间往往比你真实的处理时间要多很多。但一些耗时的操作比如I/O访问,DB查询,远程调用,这些如果可以并行的话,则开启并行流是可提升很大性能的。因为并行流的底层原理是fork/join,如果你的数据分块不是很好切分,也不建议开启并行流。举个例子ArrayList的Stream可以开启并行流,而LinkedList则不建议,因为LinkedList每次做数据切分要遍历整个链表,这本身就已经很浪费性能,而ArrayList则不会。
有篇来自 发布在 jaxenter 的调查报告 《How misusing Streams can make your code 5 times slower》
原文地址点我进去 中文翻译版 点我进去 此文用代码实验得出了一个结论 如果你要进行stream操作 使用 iterators and for-each 效率更高
解问 lambda表达式的更多相关文章
- 【Java学习笔记之三十一】详解Java8 lambda表达式
Java 8 发布日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Java 8之前 ...
- java8函数式接口详解、函数接口详解、lambda表达式匿名函数、方法引用使用含义、函数式接口实例、如何定义函数式接口
函数式接口详细定义 函数式接口只有一个抽象方法 由于default方法有一个实现,所以他们不是抽象的. 如果一个接口定义了一个抽象方法,而他恰好覆盖了Object的public方法,仍旧不算做接口的抽 ...
- Lambda表达式常用代码示例
Lambda表达式常用代码示例 2017-10-24 目录 1 Lambda表达式是什么2 Lambda表达式语法3 函数式接口是什么 3.1 常用函数式接口4 Lambdas和Streams结合使 ...
- Java8特性详解 lambda表达式 Stream
1.lambda表达式 Java8最值得学习的特性就是Lambda表达式和Stream API,如果有python或者javascript的语言基础,对理解Lambda表达式有很大帮助,因为Java正 ...
- Lambda表达式详解(例子详解)(转自:http://blog.csdn.net/damon316/article/details/51734661)
Lambda表达式详解(例子详解) lambda简介 lambda运算符:所有的lambda表达式都是用新的lambda运算符 " => ",可以叫他,“转到”或者 ...
- lambda表达式,filter,map,reduce,curry,打包与解包和
当然是函数式那一套黑魔法啦,且听我细细道来. lambda表达式 也就是匿名函数. 用法:lambda 参数列表 : 返回值 例: +1函数 f=lambda x:x+1 max函数(条件语句的写法如 ...
- Python解包参数列表及 Lambda 表达式
解包参数列表 当参数已经在python列表或元组中但需要为需要单独位置参数的函数调用解包时,会发生相反的情况.例如,内置的 range() 函数需要单独的 start 和 stop 参数.如果它们不能 ...
- Java 8 Lambda 表达式详解
一.Java 8 Lambda 表达式了解 参考:Java 8 Lambda 表达式 | 菜鸟教程 1.1 介绍: Lambda 表达式,也可称为闭包,是推动 Java 8 发布的最重要新特性. La ...
- 类型:.net;问题:C#lambda表达式;结果:Lambda表达式详解
Lambda表达式详解 前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸夸lambda吧:简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1 ...
随机推荐
- [大数据测试]ETL测试或数据仓库测试入门
转载自: http://blog.csdn.net/zhusongziye/article/details/78633934 概述 在我们学习ETL测试之前,先了解下business intellig ...
- TC-572-D1L2 未完!待续!
题目描述 • 有一个神秘的常数 K ,s 位• 现在有 n 个 s 位数,告诉你每个数与 K 有多少位是相同的• 判断 K 的无解.多解.唯一解,并求出唯一解(如果存在的话)• 所有出现的数都允许前导 ...
- ASP.NET 网站部署到IIS上如何进行调试
1:在一个网站成功部署后,有可能会遇到一些错误,但是又不能直接看出错误源(如果能在源程序里下断点进行调试就好了,这样就能准确的找出错误代码),下面介绍如何在一个已经部署的网站上进行断点调试(前提有网站 ...
- oracle05
1. 数据处理 说完了所有的查询,下面说说增.删.改. 1.1. Update 在plsql Developer工具中,加上rowid可以更改数据. 使用工具进行更新数据的操作 在工具中更新数据方式一 ...
- 【矩阵】RQ/QR 分解
Multiple View Geometry in Computer Vision A.4.1.1 (page 579) 将一个 3x3 矩阵 $ A $ 进行 RQ 分解是将其分解成为一个上三角阵 ...
- xmlHttpRequest 跨域和上传或下载进度条
跨域 XMLHttpRequest 请求 普通网页能够使用XMLHttpRequest对象发送或者接受服务器数据, 但是它们受限于同源策略. 扩展可以不受该限制. 任何扩展只要它先获取了跨域请求许可, ...
- Runtime - 消息发送原理
Runtime - 消息发送原理. Objective-C运行时的核心就在于消息分派器objc_msgSend,消息分派器把选择器映射为函数指针,并调用被引用的函数. 要想理解objc_msgSend ...
- django Rest Framework----认证/访问权限控制/访问频率限制 执行流程 Authentication/Permissions/Throttling 源码分析
url: url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})) 为例 当django启动的时候,会调用执行vie ...
- parseObject方法将json字符串转换成Map
String nwVal=recordDO.getWorkOrderNwVal(); HashMap<String,WxhcWorkOrderDO> nwMap=JSON.parseObj ...
- 16 Go Concurrency Patterns: Timing out, moving on GO并发模式: 超时, 继续前进
Go Concurrency Patterns: Timing out, moving on GO并发模式: 超时, 继续前进 23 September 2010 Concurrent progra ...