一、什么是lambda表达式?
Lambda 表达式,其实就是匿名函数。而函数其实就是功能(function),匿名函数,就是匿名的功能代码了,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。Lambda就是为了替换匿名函数而存在的【本人的理解】;
二、lambda的使用场景。
Lambda表达式是用于替代匿名函数,写出更简洁的代码的,因此,所有期待匿名函数、或者函数式接口类型参数出现的地方都可以使用Lambda替换。
三、什么是函数式接口。
函数式接口:Functional Interface.
定义的一个接口,接口里面必须 有且只有一个抽象方法 ,这样的接口就成为函数式接口。
在可以使用lambda表达式的地方,方法声明时必须包含一个函数式的接口,匿名内部类其实是函数式接口的实现类。
(JAVA8的接口可以有多个default方法)
四、写法、规则
基本语法:
(parameters) -> expression 或 (parameters) ->{ statements; }
即: 参数 -> 带返回值的表达式/无返回值的陈述
----------
//1. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y;
//2. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s);
----------
lambda表达式的结构
参数可以是零个或多个
参数类型可指定,可省略(根据表达式上下文推断)
参数包含在圆括号中,用逗号分隔
表达式主体可以是零条或多条语句,包含在花括号中
表达式主体只有一条语句时,花括号可省略
表达式主体有一条以上语句时,表达式的返回类型与代码块的返回类型一致
表达式只有一条语句时,表达式的返回类型与该语句的返回类型一致
//零个
()-> System.out.println("no argument");
//一个
x->x+1
//两个
(x,y)->x+y
//省略参数类型
View.OnClickListener oneArgument = view->Log.d(TAG,"one argument");
//指定参数类型
View.OnClickListener oneArgument = (View view)->Log.d(TAG,"one argument");
//多行语句
//返回类型是代码块返回的void
View.OnClickListener multiLine = (View view)->{
Log.d(TAG,"multi statements");
Log.d(TAG,"second line");
}
//返回类型是表达式主体语句的返回类型int
(int x)->x+1
五.几个特性
1. 类型推导
编译器负责推导lambda表达式的类型。它利用lambda表达式所在上下文所期待的类型进行推导,
这个被期待的类型被称为目标类型。就是说我们传入的参数可以无需写类型了!
六、demo
1.使用lambda表达式实现Runnable
package com.lz.test;
/**
* 使用lambda表达式替换Runnable匿名内部类
* @author MingChenchen
*
*/
public class RunableTest {
/**
* 普通的Runnable
*/
public static void runSomeThing(){
//new Runnable()实际上实现的接口的匿名子类;
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("I am running");
}
};
new Thread(runnable).start();
}
/**
* 使用lambda后的
*/
public static void runSomeThingByLambda(){
//此处期待的是一个函数式类型的参数,因此可以使用lambda表达式进行替换;
new Thread(() -> System.out.println("I am running")).start();
}
public static void main(String[] args) {
//runSomeThing();
runSomeThingByLambda();
}
}
上述代码中:
() -> System.out.println(“I am running”)就是一个lambda表达式,
可以看出,它是替代了new Runnable(){}这个匿名内部类。
2.使用lambda表达式实现Comparator
Students.java
----------
package com.lz.test;
/**
* Lambda表达式测试实体;
* @author JunZhou
* @Time 2018年1月29日下午10:44:56
*/
public class Students {
private int age;
private int score;
public Students(int age, int score) {
super();
this.age = age;
this.score = score;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
package com.lz.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class LambdaTestDemo {
public static void main(String[] args) {
List<Students> students = new ArrayList<Students>();
students.add(new Students(23, 100));
students.add(new Students(27, 98));
students.add(new Students(29, 99));
students.add(new Students(29, 98));
students.add(new Students(22, 89));
// 未使用lambda表达式之前的代码;
/*
* Collections.sort(students, new Comparator<Students>() {
*
* @Override public int compare(Students o1, Students o2) { int i =
* o1.getScore() - o2.getScore(); if(i == 0){ return o1.getAge() -
* o2.getAge(); } return i; } });
*/
// 使用lambda表达式替换之后的代码;
Collections.sort(students, (Students o1, Students o2) -> {
int i = o1.getScore() - o2.getScore();
if (i == 0) {
return o1.getAge() - o2.getAge();
}
return i;
});
for (Students stu : students) {
System.out.println("score:" + stu.getScore() + ":age" + stu.getAge());
}
}
}