Java 8 Lambda表达式学习和理解
Java 8 Lambda表达式和理解
说明:部分资料来源于网络
时间:20190704
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑。
一、语法
1、lambda 表达式的语法格式如下:
(左边)输入参数->(右边)lambda主体
(parameters) -> expression;
或
(parameters) ->{ statements; }
2、以下是lambda表达式的重要特征:
(1)输入参数:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:
a、一个参数无需定义圆括号,但多个参数需要定义圆括号。
b、如果申明了参数类型,则一定需要圆括号。
(2)lambda主体:
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
3、按照上面的格式,lambda不同参数的表达式写法
(1)没有参数的表达式:
() -> System.out.println("this is no parameter Lambda expression");
(2)只有一个参数的表达式:
(x) -> System.out.println("this is only one parameter Lambda expression");
或者
(X x) -> System.out.println("this is only one parameter Lambda expression");
和
(x) -> {
x = x*2;
System.out.println("this is only one parameter Lambda expression");
System.out.println("the function is double input value");
return x;
};
说明:一个参数的可以不用使用(),如果参数声明了参数类型则必须要加();Lambda主体是语句块的话需要使用{}。
(3)有两个或者多个参数的表达式:
(x,y) -> System.out.println("these are several parameters Lambda expression");
或者
(X x,Y y) -> {
System.out.println("the function is add two input values");
System.out.println("these are several parameters Lambda expression");
return x+y;
};
说明:有多个参数的lambda表达式,参数使用,隔开。Lambda主体是语句块的话需要使用{}。
二、Lambda 表达式实例
lambda示例1:
/*
* Predicate<T>接口中boolean test(T t)方法只接收一个参数,返回值为boolean类型,
* 故lambda表达式的输入参数只有一个参数:x,lambda的主体返回值为boolean类型
*/
Predicate<Integer> atLeast5 = x -> x >= 5;
System.out.println("传入参数是否大于5:" + atLeast5.test(6)); /*
* BinaryOperator<T>接口中R apply(T t, U u)方法接收两个泛型参数,返回值为也为泛型
* 故lambda表达式输入Long参数有两个:x,y,lambda的主体返回值为Long类型
*/
BinaryOperator<Long> addLongs = (x, y) -> {
Long z = x + y;
return z;
};
System.out.println("计算传入两个Long参数的和:" + addLongs.apply(5l, 6l)); /*
* Runnable接口中run()方法没有参数,有没有返回值,故lambda表达式没有参数,lambda主体也没有返回值
*/
Runnable run1 = () -> System.out.println("这个方法就是run里面的方法");
run1.run(); try {
final Integer value = 9;
/*
* 1、Callable<V>接口中V call() throws Exception方法没有参数,故lambda表达式也不能有输入参数,
* 返回类型为泛型,故lambda主体需要返回指定Integer类型
* 2、因为.call()方法抛出异常,所以需要抛出或者捕获异常
* 3、lambda表达式使用外部参数,需要是final类型,及时外部参数没有定义为final类型,
* 也会隐式的指定为final,故值或者引用地址不能修改。
*/
Callable<Integer> call = () -> value;
System.out.println("无参的方法,所以lambda的参数列表中不能传递参数:" + call.call());
} catch (Exception e) {
e.printStackTrace();
}
lambda示例二:
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);
}
// 定义方法,方法通过lambda表达式实现了接口中的方法
private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
} }
执行以上代码,输出结果为:
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google
使用 Lambda 表达式需要注意以下两点:
Lambda表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。
Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
Lambda表达式常用的场景是:函数式接口。函数式接口是指的只有一个抽象方法的接口,我们常用的函数式接口有:
Runnable、Callable、PrivilegedAction、Comparator、FileFilter、PathMatcher、InvocationHandler、PropertyChangeListener、ActionListener、ChangeListener、Function、Predicate、BinaryOperator
三、lambda表达式中的变量作用域
lambda表达式只能引用标记了final的外层局部变量,这就是说不能在lambda内部修改定义在域外的局部变量,否则会编译错误。
在 Java8Tester.java 文件输入以下代码:
public class Java8Tester {
final static String salutation = "Hello! ";
public static void main(String args[]){
GreetingService greetService1 = message -> System.out.println(salutation + message);
greetService1.sayMessage("Runoob");
//====================相当于下面==============================
GreetingService g = new GreetingService() {
@Override
public void sayMessage(String message) {
System.out.println(salutation + message);
}
};
g.sayMessage("jack");
}
interface GreetingService {
void sayMessage(String message);
}
}
执行以上脚本,输出结果为:
$ javac Java8Tester.java
$ java Java8Tester
Hello! Runoob
Hello! jack
我们也可以直接在 lambda 表达式中访问外层的局部变量:
public class Java8Tester {
public static void main(String args[]) {
final int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2); // 输出结果为 3
}
public interface Converter<T1, T2> {
void convert(int i);
}
}
lambda表达式的局部变量可以不声明为final,但是不可被后面的代码修改(即隐性的具有final 的语义)
int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5; //报错信息:Local variable num defined in an enclosing scope must be final or effectively final
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); //编译会出错
Java 8 Lambda表达式学习和理解的更多相关文章
- Java中lambda表达式学习
一.Lambda表达式的基础语法: Java8中引入了一个新的操作符"->"该操作符称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分为两部分: 左侧:L ...
- java lambda表达式学习笔记
lambda是函数式编程(FP,functional program),在java8中引入,而C#很早之前就有了.在java中lambda表达式是'->',在C#中是‘=>’. 杜甫说:射 ...
- Java基础学习总结(44)——10个Java 8 Lambda表达式经典示例
Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Ja ...
- Java 8 Lambda表达式
Java 8 Lambda表达式探险 http://www.cnblogs.com/feichexia/archive/2012/11/15/Java8_LambdaExpression.html 为 ...
- Java 8 Lambda表达式10个示例【存】
PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...
- Lambda 表达式 学习
最近几天在学习Lambda,给我的理解就是一个匿名函数的升级版,代码极大可能的简洁了很多,不需要像以前一样必须使用众多的代码才能实现相关功能. 慢慢积累学习,将Java 8的相关知识进行一个学习. 用 ...
- 深入浅出 Java 8 Lambda 表达式
摘要:此篇文章主要介绍 Java8 Lambda 表达式产生的背景和用法,以及 Lambda 表达式与匿名类的不同等.本文系 OneAPM 工程师编译整理. Java 是一流的面向对象语言,除了部分简 ...
- Java 8 Lambda 表达式
Lambda 是啥玩意 简单来说,Lambda 就是一个匿名的方法,就这样,没啥特别的.它采用一种非常简洁的方式来定义方法.当你想传递可复用的方法片段时,匿名方法非常有用.例如,将一个方法传递给另外一 ...
- Java 8 lambda表达式示例
例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例.看一下Java 8之前的runna ...
随机推荐
- 应用在Windows系统中的自动化部署实践
因为公司的产品有linux 和windows两套部署环境,领导安排我先来做windows的自动化部署.由于本人对windows 的dos命令基本没啥概念,所以在最终完成之前,走了很多弯路,在这里记载下 ...
- 运输层6——TCP可靠传输的实现
目录 1. 以字节为单位的滑动窗口 2. 超时重传时间的选择 写在前面:本文章是针对<计算机网络第七版>的学习笔记 运输层1--运输层协议概述 运输层2--用户数据报协议UDP 运输层3- ...
- 记一个VS连接过程中找不到cpp的解决方法
在新增几个qt页面时,发现原来没动的几个cpp 连接报错了,错误均是qt的相关文件找不到 应该是moc文件没有生产或者没有被包含进工程.我想着既然我没动,应该不会是moc的原因,就在其他方向解决了很久 ...
- springcloud注册中心Eureka<英 [juəˈri:kə]>的基本搭建
1.http://start.spring.io搭建基本的springboot环境,版本用的是1.5.10 2.在pom文件中添加注册中心的jar包和springcloud的jar包 <!-- ...
- 使用openoffice转pdf,详细
期由于项目的需求,需要word文档转pdf在线预览,由于一直没有接触这块,所以花了将近四天时间才弄明白. 写这篇文章的主要目的是加深自己的记忆,同时方便以后在用. (最近有使用了这个功能,发现这篇文章 ...
- [Dart] Capture and Handle Data Sequences with Streams in Dart
Streams represent a sequence of asynchronous events. Each event is either a data event, also called ...
- Qt进程间通信
Qt 提供了四种进程间通信的方式: 使用共享内存(shared memory)交互:这是 Qt 提供的一种各个平台均有支持的进程间交互的方式. TCP/IP:其基本思想就是将同一机器上面的两个进程一个 ...
- 定时器( setInterval和 setTimeout)
一.定时器setInterval-------常用的,反复循环的 <input type="button" value="停止" id="btn ...
- 对象(面向对象、创建对象方式、Json)
一.面向对象 面向过程:凡事亲力亲为,每件事的具体过程都要知道,注重过程 面向对象:根据需求寻找对象,所有的事都用对象来做,注重结果 面向对象特性:封装.继承.多态(抽象性) js是一门基于对象的语言 ...
- [APIO2012]派遣 左偏树
P1552 [APIO2012]派遣 题面 考虑枚举每个节点作为管理者,计算所获得的满意程度以更新答案.对于每个节点的计算,贪心,维护一个大根堆,每次弹出薪水最大的人.这里注意,一旦一个人被弹出,那么 ...