Java8 Lambda使用指南
Java8 Lambda 的使用指南
原文地址:https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#syntax
对于匿名内部类存在一个问题,如果接口只有一个方法,那么该接口的匿名内部类的实现将看起来很臃肿,lambda表达式将可以让你的实现更加优雅。
如果打算将一个方法作为一个参数传入另一个方法,例如对按钮的点击事件做出响应,那么lambda将帮你更容易的实现。
使用lambda的几个场景的场景.
场景1,从列表中找出符合条件的人员(年龄大于18岁的人)
public class Person {
public enum Gender{
MALE, FEMALE
}
private String name;
private Gender sex;
private Integer age;
public String getInfo(){
return toString();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Gender getSex() {
return sex;
}
public void setSex(Gender sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
getAgeOlderThan(ps,18);
}
public static void getAgeOlderThan(List<Person> ps, int age) {
for (Person p: ps) {
if(p.getAge() > age){
System.out.println(p.getInfo());
}
}
}
}
场景2,如果上面的查询条件变动,那就需要重写代码(查询条件改为,在50岁与18岁之间的人)
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
getAgeBetween(ps,18,50);
}
public static void getAgeBetween(List<Person> ps, int down,int up) {
for (Person p: ps) {
if(p.getAge() > down && p.getAge() < up){
System.out.println(p.getInfo());
}
}
}
}
场景3,可以看到上面的实现,每当出现一个新的查询条件,都需要新添加一个方法,我们想到引入接口使用多态来覆盖不同场景,引入用来做判断的接口PersonChecker和他的实现类CheckPersonWithGender。如果需要修改需求,只需要在添加一个实现类,比方说通过name来查找,只需要额外添加要给CheckPersonWithName类。
public interface CheckPerson {
boolean check(Person p);
}
// 找出所有性别为指定类型的人
public class CheckPersonWithGender implements CheckPerson{
@Override
public boolean check(Person p) {
if(p.getSex().equals(Person.Gender.FEMALE)){
return true;
}
return false;
}
}
// 找出所有名字为pikzas的人
public class CheckPersonWithName implements CheckPerson{
@Override
public boolean check(Person p) {
if(p.getName().equals("pikzas")){
return true;
}
return false;
}
}
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
getByFilter(ps,new CheckPersonWithGender());
getByFilter(ps,new CheckPersonWithName());
}
public static void getByFilter(List<Person> ps,CheckPerson checker) {
for (Person p: ps) {
if(checker.check(p)){
System.out.println(p.getInfo());
}
}
}
}
场景4,上面的接口的引入方便了我们使用多态来扩展系统,但是每针对一个特定的过滤条件,我们都需创建一个新的接口实现类,于是可以通过匿名类的方式来将实现简化
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
// 此处通过匿名类的方式避免了新创建一个类
getByFilter(ps,new CheckPerson(){
@Override
public boolean check(Person p) {
return p.getAge() > 50;
}
});
}
public static void getByFilter(List<Person> ps,CheckPerson checker) {
for (Person p: ps) {
if(checker.check(p)){
System.out.println(p.getInfo());
}
}
}
}
场景5,可以看到上面通过内部类的方式已经使代码相当精简,但是还是有内部类的存在,于是便在Java8中推出了Lambda来替换这种只有一个方法需要实现的内部类,将代码再次简化。
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
// 此处通过一个lambda表达式清晰明了的替换了一大堆内部类的实现
getByFilter(ps,(Person p) -> p.getAge() > 18);
}
public static void getByFilter(List<Person> ps,CheckPerson checker) {
for (Person p: ps) {
if(checker.check(p)){
System.out.println(p.getInfo());
}
}
}
}
场景6,上面用
(Person p) -> p.getAge() > 18替换了匿名内部类,主要是需要对数据做逻辑判断的接口CheckPerson的实现。但是该接口在Java8中有官方给定的一个替代接口,java.util.function.Predicate<T>,于是又可以少定义一个接口。
public interface CheckPerson {
boolean check(Person p);
}
// 替换为
interface Predicate<T> {
boolean test(T t);
}
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
//
getByFilter(ps, p -> p.getAge() > 18);
getByPreditor(ps, (Person p) -> p.getAge() < 50);
}
public static void getByFilter(List<Person> ps,CheckPerson checker) {
for (Person p: ps) {
if(checker.check(p)){
System.out.println(p.getInfo());
}
}
}
// 使用 Predicate<Person> checker 替换了 CheckPerson checker 进一步抽象,使接口变得更为通用
// 对应用来做条件判定的方法变为Predicate中的test方法
public static void getByPreditor(List<Person> ps,Predicate<Person> checker) {
for (Person p: ps) {
if(checker.test(p)){
System.out.println(p.getInfo());
}
}
}
}
场景7,上面的例子都是简单的将符合条件的对象打印了出来,同理于官方定义Predicate<T>用来对数据做过滤,Java8还提供了一个接口Consumer<T>来定义对满足条件的数据该执行的动作。
public interface Consumer<T> {
void accept(T t);
}
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
getByFilter(ps, p -> p.getAge() > 18);
getByPreditor(ps, p -> p.getAge() < 50);
getByPreditorAndActByConsumer(
ps,
p-> p.getAge() > 18 && p.getAge() < 50, // 对Predicate接口中test方法的实现
p -> System.out.println(p.getInfo())); // 对Consumer接口中accept方法的实现
}
public static void getByFilter(List<Person> ps, CheckPerson checker) {
for (Person p : ps) {
if (checker.check(p)) {
System.out.println(p.getInfo());
}
}
}
public static void getByPreditor(List<Person> ps, Predicate<Person> checker) {
for (Person p : ps) {
if (checker.test(p)) {
System.out.println(p.getInfo());
}
}
}
// 对符合条件的数据应用动态的处理方式
public static void getByPreditorAndActByConsumer(List<Person> ps, Predicate<Person> checker, Consumer<Person> consumer) {
for (Person p : ps) {
if (checker.test(p)) {
consumer.accept(p);
}
}
}
}
场景8,如果对于满足条件的数据需要额外的处理,然后再交给Consumer方法来执行动作,Java8提供了,例如我需要将每个人男性的年龄都加10,然后打印出来。
public interface Function<T, R> {
R apply(T t);
}
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
ps.add(new Person("alex",Person.Gender.MALE,24));
ps.add(new Person("Blex",Person.Gender.MALE,29));
getByPreditorAndActByConsumerAndHandleWithFunction(
ps,
p-> p.getAge() > 18 && p.getAge() < 50, // 对Predicate接口中test方法的实现
p -> p.getAge() + 10 ,
p -> System.out.println(p)); // 对Consumer接口中accept方法的实现
}
// 对符合条件的数据应用动态的处理方式
public static void getByPreditorAndActByConsumerAndHandleWithFunction(List<Person> ps, Predicate<Person> checker, Function<Person,Integer> function, Consumer<Integer> consumer) {
for (Person p : ps) {
if (checker.test(p)) {
Integer ret = function.apply(p);
consumer.accept(ret);
}
}
}
}
lambda的格式
从前面已经可以看到 lanmda主要由三部分构成 形参部分表达式 -> 逻辑代码表达
形参部分表达式的标准写法是(ParamA a,ParamB b,....),参数类型可以省略,如果入参个数只有一个,那么小括号也能省略。
public class Demo {
public static void main(String[] args) {
List<Person> ps = new ArrayList<Person>();
getByPreditorAndActByConsumerAndHandleWithFunction(
ps,
p -> p.getAge() > 18 && p.getAge() < 50, // 单个参数,直接写形参
(Person p) -> p.getAge() + 10 , // 单个参数,用括号包围起来,写上参数类型
(p) -> System.out.println(p)); // 单个参数,用括号包围起来,不写上参数类型
}
// 对符合条件的数据应用动态的处理方式
public static void getByPreditorAndActByConsumerAndHandleWithFunction(List<Person> ps, Predicate<Person> checker, Function<Person,Integer> function, Consumer<Integer> consumer) {
for (Person p : ps) {
if (checker.test(p)) {
Integer ret = function.apply(p);
consumer.accept(ret);
}
}
}
}
public class MultiParam {
public interface MathMethod{
int operation(int a, int b);
}
public int doRun(int a, int b, MathMethod method){
return method.operation(a,b);
}
public static void main(String[] args) {
MathMethod addOp = (int a,int b) -> a+b; // 入参用括号围起来,标明入参数据类型
MathMethod subOp = (a,b) -> a-b; // 入参用括号围起来,不标数据类型
MultiParam demo = new MultiParam();
System.out.print("23 + 55 = ");
System.out.print(demo.doRun(23,55,addOp));
System.out.println();
System.out.print("55 + 22 = ");
System.out.print(demo.doRun(55,22,subOp));
}
}
逻辑代码表达的标准写法为{return expression},在实现的接口方法不是void的情况下,可以同时将花括号和return省略,如果接口方法是void返回。则不能写return。
public class MultiParam {
public interface MathMethod{
int operation(int a, int b); // 接口内方法不是void
}
public int doRun(int a, int b, MathMethod method){
return method.operation(a,b);
}
public static void main(String[] args) {
MathMethod addOp = (int a,int b) -> {return a+b;}; // 这时是一个标准写法,应为接口方法不是void,所以return必须存在。
MathMethod subOp = (a,b) -> a-b; // {}和return可以同时去掉
MultiParam demo = new MultiParam();
System.out.print("23 + 55 = ");
System.out.print(demo.doRun(23,55,addOp));
System.out.println();
System.out.print("55 + 22 = ");
System.out.print(demo.doRun(55,22,subOp));
}
//之前的Consumer里面的accept方法返回值为void 就可以通过如下方式来写
(p) -> {System.out.println(p)}; // 带上花括号,但是括号里面不能有return,因为这是lambda实现的接口方法返回的void。
(p) -> System.out.println(p); // 省略花括号,同理return 也不能存在。
Java8 Lambda使用指南的更多相关文章
- java8 Lambda表达式的新手上车指南(1)
背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...
- java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口
背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...
- 【Java学习笔记之三十一】详解Java8 lambda表达式
Java 8 发布日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Java 8之前 ...
- java8 快速入门 lambda表达式 Java8 lambda表达式10个示例
本文由 ImportNew - lemeilleur 翻译自 javarevisited.欢迎加入翻译小组.转载请见文末要求. Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发 ...
- JAVA8 Lambda初体验
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.u ...
- Java8 lambda表达式10个示例
Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Ja ...
- java8 Lambda表达式的10个例子(转)
原文:http://jobar.iteye.com/blog/2023477 Java8中Lambda表达式的10个例子 例1 用Lambda表达式实现Runnable接口 Java代码 收藏代码// ...
- Java8 Lambda表达式详解手册及实例
先贩卖一下焦虑,Java8发于2014年3月18日,距离现在已经快6年了,如果你对Java8的新特性还没有应用,甚至还一无所知,那你真得关注公众号"程序新视界",好好系列的学习一下 ...
- Java8 lambda表达式10个示例<转>
例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例.看一下Java 8之前的runna ...
随机推荐
- Gogs的Docker容器化部署流程遇到的问题
Gogs的Docker容器化部署流程遇到的问题 最近在学习CI/CD的一些方案,个人比较青睐容器化轻量级.CI方面一开始是想使用gitlab的,但是发现我自己买的服务器配置太低,内存根本不够(大写 ...
- opensuse安装pycharm
最近在学习python,所以查询了很多资料,大多都推荐pycharm进行pychon项目开发.于是查阅一些资料,整理出这个安装步骤.(仅供参考!!!仅供参考!!!仅供参考!!!) 仅供参考!!!仅供参 ...
- P1010 幂次方(分治)
https://www.luogu.com.cn/problem/P1010 刚刚看到这个题时,有点懵,如果说这是个数学题 比如说7,应该先求出7 = 4 + 2 + 1; 即先分解出里面应该有最多的 ...
- 【Python】字符串处理方法
- 完整安装IIS服务
此文主要是针对前面提到的 IIS支持json.geojson文件 添加脚本映射时,提示找不到asp.dll时的解决方法. 主要参考了此文:http://www.kodyaz.com/articles/ ...
- SSM开发基于Java EE在线图书销售系统
SSM(Spring+Spring MVC+MyBatis)开发基于Java EE在线图书销售系统 网站成功建立和运行很大部分取决于网站开发前的规划,因此为了在网站建立过程中避免一些不 ...
- django 完成登录功能
啃了几天文档,感觉能理解了这个框架,但是真的下手的时候真的不知道从何开始. orm即Object-Relationl Mapping,看这名字就是操作数据库的,用过ssm,不过django操作数据库是 ...
- Python列表和字典的简单实操例子
# coding=utf-8 name_l = [] passwd_l = [] money_l = [] goods = {} index = 0 def input_user(): print(& ...
- 排队看病(PriorityQueue自定义排序)
看病要排队这个是地球人都知道的常识. 不过经过细心的0068的观察,他发现了医院里排队还是有讲究的.0068所去的医院有三个医生(汗,这么少)同时看病.而看病的人病情有轻重,所以不能根据简单的先来先服 ...
- LUT
FPGA大多为LUT+寄存器的够,实现工艺为SRAM:寄存器很好理解,存储器的一种,用于存储指令和数据,多位于CPU内.拿什么是LUT呢? LUT:即Look up table,查找表,其本质是一个R ...