java 8 lambda reduce_JDK8新特性Lambda表达式体验
“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。
Lambda简介
Lambda表达式的语法由参数列表、箭头符号->和函数体组成。函数体既可以是一个表达式,也可以是一个语句块。
比如:
(int x, int y) -> x + y;
具体的Lambda表达式的介绍可以看这篇博客,写得挺详细的。
Java Lambda表达式示例
下面就用一些例子来体验一下Lambda表达式。
遍历集合
比如我们现在要遍历一个List:
List list = Arrays.asList("Hello", "JDK8", "and", "Lambda");
JDK8之前的写法:
for (String s : list) {
System.out.println(s);
}
用Lambda表达式写法:
list.forEach(s -> System.out.println(s));
可以看到,无论是代码量和可读性都得到了提高。
在此基础上还可以再用隐式表达式进行简化:
list.forEach(System.out::println);
匿名类
在Java中很多时候我们要用到匿名类,比如线程Runnable、FileFilter和Comparator等等。
而匿名类型最大的问题就在于其冗余的语法。
这里用Comparator做例子。
比如我们有一个Cat类,表示猫,有名字、高度和重量这些属性。
package com.fengyuan.model;
import lombok.AllArgsConstructor;
import lombok.Data;
public @Data @AllArgsConstructor class Cat {
private String name;
private double height;
private double weight;
}
我们创建3只猫,存到List中:
List catList = new ArrayList<>();
// 请无视这些数据的合理性,我乱写的
catList.add(new Cat("cat1", 10.3, 3.6));
catList.add(new Cat("cat2", 9.3, 4.6));
catList.add(new Cat("cat3", 9.5, 4.0));
然后我们现在要对这个List进行排序,但是现在不知道是要怎么排,所以我们要定义一个比较器,指定用高度或者是重量来排序。
JDK8之前的写法:
// 指定用高度来排序
Collections.sort(catList, new Comparator() {
@Override
public int compare(Cat o1, Cat o2) {
if (o1.getHeight() > o2.getHeight()) {
return 1;
} else if (o1.getHeight() < o2.getHeight()) {
return -1;
} else {
return 0;
}
}
});
而用Lambda,可以这样写:
Collections.sort(catList, (o1, o2) -> {
if (o1.getHeight() > o2.getHeight()) {
return 1;
} else if (o1.getHeight() < o2.getHeight()) {
return -1;
} else {
return 0;
}
});
继续用方法引用,可以简写到极致:
// 指定用重量排序
catList.sort(Comparator.comparing(Cat::getWeight));
// 要逆向排列也很简单
catList.sort(Comparator.comparing(Cat::getWeight).reversed());
到最后这种写法,已经简写到极致,而且可读性非常高。
函数式接口
JDK8增加了一个新的包:java.util.function,它里面包含了常用的函数式接口,比如Predicate、Consumer,Function等等。
接下来就体验一下Predicate和Consumer的用法。
我们现在有一个订单类,有id,金额,运费这些属性。这个订单有一个折扣方法,我们希望能够根据营销活动,动态修改优惠方案。
Order类:
package com.fengyuan.model;
import java.util.function.Consumer;
import java.util.function.Predicate;
import lombok.AllArgsConstructor;
import lombok.Data;
public @Data @AllArgsConstructor class Order {
private long id;
private double payment;
private double freight;
// 优惠政策
public Order discount(Order order, Predicate predicate, Consumer consumer) {
// 满足Predicate的条件,返回true
if (predicate.test(order)) {
// 接收订单对象,对订单对象进行处理
consumer.accept(order);
}
return order;
}
}
其中
Predicate:接收T对象并返回boolean。
Consumer:接收T对象,没有返回值。
然后通过函数式编程,我们可以动态传入我们的优惠方案,比如99包邮:
// 新建一个订单,506.5的金额,10.0的运费
Order order = new Order(123, 506.5, 10.0);
// 满足金额>=99的条件,则设置运费为0
order.discount(order,
o -> o.getPayment() >= 99,
o -> o.setFreight(0));
这样一来,就能根据营销活动,修改我们的优惠方案。
除此之外,Predicate对象之间还能运用与或非这些逻辑操作,比如:
predicate1.and(predicate2);
predicate1.or(predicate2);
Stream
这里的Stream和I/O流不同,它更像具有Iterable的集合类。
Stream API引入的目的在于弥补Java函数式编程的缺陷,让java也支持map()、reduce()等函数式编程语言。
map
map(映射),将传入的函数依次作用到序列的每个元素。
比如说,有一个字符串列表,我们现在给列表里每个字符串调用toLowerCase()方法,转成小写字母。
List list = Arrays.asList("Hello", "JDK8", "and", "Lambda");
转成小写,用collect()把Stream再转回List,返回新的列表:
List newList = list.stream().map(s -> s.toLowerCase()).collect(Collectors.toList());
也可以返回一个字符串,指定连接符,我这里是用空格连接的:
String str = list.stream().map(s -> s.toLowerCase()).collect(Collectors.joining(" "));
也可以用隐式函数,String::toLowerCase来实现:
String str = list.stream().map(String::toLowerCase).collect(Collectors.joining(" "));
reduce
reduce(归约),将集合中所有值结合起来。
将一个整型List,先进行map:每个数都翻一倍,再进行reduce:所有数加起来,得到结果:
List numbers = Arrays.asList(10, 20, 30, 40, 50);
int result = numbers.stream().map(num -> num * 2).reduce((r, num) -> r += num).get();
变量捕捉
一个简单的例子,算出一个集合中最大值、最小值、平均值等等。
集合:
List numbers = Arrays.asList(4, 6, 65, 3, 44, 2, 17, 19);
计算:
int max = numbers.stream().mapToInt(x -> x).max().getAsInt();
int min = numbers.stream().mapToInt(x -> x).min().getAsInt();
long count = numbers.stream().mapToInt(x -> x).count();
double avg = numbers.stream().mapToInt(x -> x).average().getAsDouble();
int sum = numbers.stream().mapToInt(x -> x).sum();
也可以用IntSummaryStatistics类来得到统计结果:
IntSummaryStatistics stat = numbers.stream().mapToInt(x -> x).summaryStatistics();
int max = stat.getMax();
int min = stat.getMin();
long count = stat.getCount();
double avg = stat.getAverage();
long sum = stat.getSum();
结语
虽然平时项目的开发中还是比较少用到Lambda表达式,但是在以上这些体验中,确实是感受到了它的魅力。
相关文章:

php display_errors
// 检测开发环境public function setReporting(){if (APP_DEBUG true) {error_reporting(E_ALL);ini_set(display_errors,On);} else {error_reporting(E_ALL);ini_set(display_errors,Off);ini_set(log_errors, On);ini_set(error_log, RUNTIME_PATH. logs/error.log);}} 在p…

linux esd转iso,window_Win10 TH2正式版10586官方ESD映像怎么转换成ISO镜像?,今天phpstudy分享了Win10 TH2(Build - phpStudy...
Win10 TH2正式版10586官方ESD映像怎么转换成ISO镜像?今天phpstudy分享了Win10 TH2(Build 10586)各版本官方ESD映像下载地址,不过旧转换工具可能已不适用于新版ESD映像,特别是新版本增加了专业版和家庭版二合一映像,而以往都是单版本。本文使…

mysql在线上建索引,mysql 5.6在线DDL建索引测试
基本信息:mysql版本:(product)rootlocalhost [(none)]> select version;------------| version |------------| 5.6.29-log |------------1 row in set (0.00 sec)表payment的记录数:(product)rootlocalhost [sakila]> select count(*) from paym…

接口测试(postman jmeter)
接口:把client(前端)和server(后端)联系起来的就是接口,接口测试就是功能测试,进行接口测试首先得需要接口文档。 json是一种通用的数据格式,接口返回的数据都是json,jso…

c语言中delay找不到标识符,51单片机的c语言,请问哪里错了?延时没有效果,但是编译又不报错。delay应该怎么写,怎么引用啊?...
最佳答案西岸风2019-01-07 15:15i){LED00;LED21;LED40;delay(5000);}void main(void){while(1){for(i0;i<10;sbit LED0P1^0;sbit LED1P1^1;sbit LED4P1^4;sbit LED5P1^5;sbit LED2P1^2;sbit LED3P1^3;unsigned char i;sbit LED6P1^6;sbit LED7P1^7;void delay(unsigned int …

java 数据类型转换的一场_Java基础 — 四类八种基本数据类型
整型:整数类型int 一般的数据。long 极大的数据。short 用于特定的场合,比如底层的文件处理或者需要控制占用存储单元空间量的大数组。byte 用于特定的场合,比如底层的文件处理或者需要控制占用存储单元空间量的大数组。by…

vs 代理登入
https://msdn.microsoft.com/zh-cn/vstudio/dn771556.aspx转载于:https://www.cnblogs.com/CodingArt/p/6424180.html

php 为啥报错,php Soap 报错 求大神帮忙看看为什么
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼代码:$client new SoapClient("http://116.218.12.10:7012/businessService?wsdl", array(*trace* > true, *exceptions* > true));var_dump($client->__getFunctions());var_dump($client->__…

UWP: ListView 中与滚动有关的两个需求的实现
在 App 的开发过程中,ListView 控件是比较常用的控件之一。掌握它的用法,能帮助我们在一定程度上提高开发效率。本文将会介绍 ListView 的一种用法——获取并设置 ListView 的滚动位置,以及获取滚动位置处的项目。这里多说一句,由…

Deepin ROMS 安装详细流程
按照这个过程,完美安装,当然并不能排除会出现其他的问题。如果遇到了,那就老老实实上网搜吧。 转载于:https://www.cnblogs.com/haoorhuai/p/9502859.html

java struts2值栈ognl_Struts2 (三) — OGNL与值栈
一、OGNL表达式1.概述1.1什么是OGNL OGNL是Object-Graph Navigation Language的缩写,俗称对象图导航语言. 它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整…

c语言课程设计商品销售系统,c语言课程设计商品销售管理系统.pdf
C语言课程设计商品销售管理系统12020 年 4 月 19 日文档仅供参考商品销售管理系统目录一、 需求分析 2二、概要设计 2三、详细设计 4四、调试分析 14五、用户手册 14六、测试数据 15七、 附录 18— 1—22020 年 4 月 19 日文档仅供参考一、需求分析商品销售管理程序商品信息&am…

uploadhandler.php,WordPress Kernel Theme ‘upload-handler.php’任意文件上传漏洞
javascript中apply、call和bind的区别在JS中,这三者都是用来改变函数的this对象的指向的,他们有什么样的区别呢.在说区别之前还是先总结一下三者的相似之处:1.都是用来改变函数的this对象的指向的.2.第一个参数都是this要指向的对 ...AIX UNIX 系统管理、维护与高可用集群建设—…

selenium--driver.switchTo()
在自动化测试中,会遇到多窗口、多iframe、多alert的情况。此时,会使用driver.switchTo()来解决。 下面时关于driver.switchTo()的详细介绍: 1.多windows操作。 在页面A上操作时,点击某个元素之后,可能会打开新的窗口。…

代理模式-积木模式
代理模式-积木模式 代理模式在实际开发中的确非常常见和常用,表面上代理模式是产生出一个代理类,作为访问实际实现类的代理,控制了外界对实际代理类的访问,在此基础上增加一些增强性的功能。实际上,还将实际…

java调用系统时间函数_JAVA自学笔记:不使用系统函数来计算日期处于当年的第多少天...
前段时间练习了一个求闰年的功能,现在就可以用上啦,这次写一个不借助类库的时间函数,利用基础代码写一个计算求日期处于当年的第多少天的函数。虽然也有简单的方法,例如直接定义每月的天数累加,然后加上当月的天数就可…

c语言输入学生成绩q退出,哭诉、拜求C语言学生成绩管理系统
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼/* Note:Your choice is C IDE */#include "stdio.h"#include "stdlib.h"#include "conio.h"#include "string.h"struct student{int num;char name[20];float score1;float score2;float…

php 所有魔术方法,PHP常用的魔术方法及规则
转:https://www.cnblogs.com/wanglijun/p/10926303.html1. __construct 具有构造函数的类会在每次创建新对象时先调用此方法;初始化工作执行。2. __desstruct 对象的所有引用都被删除或者当对象被显式销毁时执行。3.__call()在对象中调用一个不可访问方法时…

mysql启动后在哪里编程_启动mysql后怎么连接数据库
推荐答案一.mysql安装百度mysql下载一个即可。只是注意一下几个重要的数据:第一个就是Port Number :3306。端口号默认3306,一般不需要改,如果改了,请记住这个端口号。第二个就是password:本地数据库密码,默…

Python 出现 can't use a string pattern on a bytes-like object
# codingutf-8import urllib.requestimport reurl http://www.163.comfile d:/test.htmldata urllib.request.urlopen(url).read() r1 re.compile(<.*?>)c_t r1.findall(data)print(c_t)发现读取下来后,运行到第9 行,出现: cant use a string pattern on a bytes-l…

2018牛客网暑期ACM多校训练营(第十场)J(二分)
题目描述: 给你n个字符串,要让它们一个一个的合并成一个串。在合并的过程中,要保证被合并的串S是合并后的串r的前缀,模式串t是串r的子序。问你将这n个字符串合并后所得到的字典序最小的串是什么。 题目分析: 首先&…

实用c语言函数源码,C语言编写简单朗读小工具(有源码)
原标题:C语言编写简单朗读小工具(有源码)最近不少人在后台留言说学C都是面对枯燥的控制台程序,能不能体现一下C语言的实际用途,今天我们就理论结合实践一把:C语言结合VBS脚本编写一个简单的朗读小工具,做一个能够发音的…

php监听订单状态,ecshop数据库订单状态判断
order_info 表刚下完订单order_status 0shipping_status 0pay_status 0取消order_status 2shipping_status 0pay_status 0确认order_status 1shipping_status 0pay_status 0已付款order_status 1shipping_status 0pay_status 2配货中order_status 1shipping_status 3pay_status…

flask异步操作_Python Flask后端异步处理(三)
前一篇博文我们已经将基础知识和环境配置进行了介绍:首先编写一个celerytask.py文件进行Celery的配置,同时耗时任务也写在该文件中from celery import Celeryfrom init import appfrom SZheConsole import SZheScanapp.config[CELERY_BROKER_URL] redis…

Codeforces Round #308 (Div. 2) C. Vanya and Scales dfs
题目链接: http://codeforces.com/contest/552/problem/C 题意: 给你100个砝码,第i个砝码质量是w^i,然后问你能不能在有m的情况下,左边和右边都放砝码,使得这个天平平衡 题解: dfs直接暴力 对于这个砝码来说,只有3种选…

java中JVM的原理【转】
一、java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序。程序开始执行时他才运行,程序结束时他就停止。你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机。 Java虚拟…

switch的case使用数组C语言,使用常量数组的元素作为switch语句中的case
我正在尝试将一组按键映射到一组命令.因为我处理来自多个地方的命令,所以我想在键和命令之间设置一个抽象层,这样如果我更改底层键映射,我就不必更改很多代码.我目前的尝试看起来像这样:// input.henum LOGICAL_KEYS {DO_SOMETHING_KEY,DO_SOMETHING_ELSE_KEY,...countof_LOGIC…

PHP上传文件函数move_upload,如何使用php中move_uploaded_file函数
我们平时上传的文件保存在临时文件夹中,例如/ tmp,但临时文件夹的内容在一段时间后会被删除,因此为了将来要使用上传文件,需要将内容保存在不太可能被任意删除的专用目录中,这时就需要使用move_uploaded_file函数&…

java的标记接口_Java中的标记接口?
我被教授,Java中的Marker接口是一个空接口,用于向编译器或JVM发送信号,实现此接口的类的对象必须以特殊方式处理,如序列化,克隆等。但最近我了解到,它实际上与编译器或JVM无关。例如,在Serializ…

Java Exception
先贴上一段Exception源码注释 1 /**2 * The class {code Exception} and its subclasses are a form of3 * {code Throwable} that indicates conditions that a reasonable4 * application might want to catch.5 *6 * <p>The class {code Exception} and any subc…