1、定义
lambda表达式(闭包):java8的新特性,lambda运行将函数作为一个方法的参数,也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁
1.1、lambda表达式的语法
基本语法:(parameters)->expression或(parameters)->{expression}
lambda表达式由三部分组成:
*parameters:类似于方法中的参数列表,这里的参数式函数式接口里的参数。这里的参数类型可以明确的声明,也可以不声明可以由JVM隐含的推断,另外当只有一个推断类型的时候可以省略圆括号
*->:可以理解为被用于的意思
*方法体:可以是表达式也可以是代码块,是函数式接口里方法的实现。代码块可以返回一个值,也可以什么都不返回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个值也可以什么都不返回
import java.util.Comparator;
import java.util.PriorityQueue;
public class Lambda01 {
public static void main(String[] args) {
//创建一个优先级队列
PriorityQueue<Integer> queue1=new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return 01-o2;
}
});
queue1.offer(2);
queue1.offer(3);
queue1.offer(4);
queue1.offer(5);
queue1.offer(6);
queue1.offer(7);
queue1.offer(1);
//取堆顶元素
System.out.println(queue1.peek());
System.out.println("lambda表达式");
PriorityQueue<Integer> queue2=new PriorityQueue<>((Integer o1, Integer o2)->{
return o1-o2;
});
queue2.offer(2);
queue2.offer(3);
queue2.offer(4);
queue2.offer(5);
queue2.offer(6);
queue2.offer(7);
queue2.offer(1);
//取堆顶元素
System.out.println(queue2.peek());
}
}
1.2、函数式接口
要了解什么是Lambda表达式,首先要先理解什么是函数式接口,函数式接口定义:一个接口有且只有一个抽象方法。
注意:
*如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
*如果我们在某个接口上声明了@FunctionInterface注解,那么编译器就会按照函数式接口的方式来要求该接口,这样的话如果有两个抽象方法,编译就会报错。所以从某种意义上来讲,只要保证接口中只有一个抽象方法,可以不加这个注解,加上了注解编译器可以帮助检测
定义:
@FunctionalInterface
interface NoParameterNoReturn {
//注意:只能有一个方法
void test();
}
2、Lambda基本使用
//加注这个就表示为一个函数式接口
@FunctionalInterface
interface TestFunctionInterface{
void say(String name);
}
public class Lambda02 {
public static void main(String[] args) {
//一般写法
TestFunctionInterface functionInterface1=new TestFunctionInterface() {
@Override
public void say(String name) {
System.out.println("hello"+name);
}
};
functionInterface1.say("respect");
//lambda写法
TestFunctionInterface functionInterface2=(name)->{
System.out.println("hell0"+name);
};
functionInterface2.say("salute");
}
}
3、语句精简:
*参数类型可以省略,如果需要省略,每个参数都需要省略
*参数的小括号里面只有一个参数时,可以省略小圆括号
*如果方法体中只有一句代码时,那么大括号可以省略
*如果方法体中只有一条语句时,其是return语句,那么大括号可以省略,且去掉return关键字
//无返回值,无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
//无返回值,一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int val);
}
//无返回值,多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a, int b);
}
//有返回值,无参数
@FunctionalInterface
interface NoParameterReturn {
int test();
}
//有返回值,一个参数
@FunctionalInterface
interface OneParameterReturn {
int test(int val);
}
//有返回值,多个参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a, int b);
}
public class lambda03 {
public static void main(String[] args) {
System.out.println("==========NoParameterNoReturn===========");
NoParameterNoReturn noParameterNoReturn = () -> {
System.out.println("无返回值,无参数的实现");
};
noParameterNoReturn.test();
//正常写法
System.out.println("==========OneParameterNoReturn===========");
OneParameterNoReturn OneParameterNoReturn = (int val) -> {
System.out.println("无返回值,一个参数的实现" + val);
};
OneParameterNoReturn.test(123);
/*//可以省略返回值类型
System.out.println("==========OneParameterNoReturn===========");
OneParameterNoReturn OneParameterNoReturn=(val)->{
System.out.println("无返回值,一个参数的实现"+val);
};
OneParameterNoReturn.test(123);
//一个参数的情况下,可以省略括号
System.out.println("==========OneParameterNoReturn===========");
OneParameterNoReturn OneParameterNoReturn=val->{
System.out.println("无返回值,一个参数的实现"+val);
};
OneParameterNoReturn.test(123);*/
System.out.println("==========MoreParameterNoReturn===========");
MoreParameterNoReturn moreParameterNoReturn = (int a, int b) -> {
System.out.println("无返回值,多个参数的实现" + a + b);
};
moreParameterNoReturn.test(123, 456);
System.out.println("==========NoParameterReturn===========");
/* //正常写法
NoParameterReturn noParameterReturn=()->{
return 10;
};
noParameterReturn.test();*/
NoParameterReturn noParameterReturn = () -> 10;
int result = noParameterReturn.test();
System.out.println(result);
System.out.println("==========OneParameterReturn===========");
/* //正常写法
OneParameterReturn oneParameterReturn=(int val)->{
return val;
};
oneParameterReturn.test(20);*/
OneParameterReturn oneParameterReturn=val->val+100;
result = oneParameterReturn.test(20);
System.out.println(result);
System.out.println("==========MoreParameterReturn===========");
MoreParameterReturn moreParameterReturn=(a,b)->{
return a+b;
};
int test = moreParameterReturn.test(123, 456);
System.out.println(test);
}
}
4、变量捕获
Lambda存在变量捕获,了解变量捕获之后,才能更好的理解Lambda的作用域,java当中的匿名内部类中,会存在变量捕获
4.1、匿名内部类
匿名内部类是局部内部类的一种简化形式,本质上是一个对象,是实现了该接口或继承了该抽象类的子类对象
语法格式: new 类名或者接口名(){重写方法;};
class Test {
public void func(){
System.out.println("func()");
}
}
public class TestDemo {
public static void main(String[] args) {
new Test(){
@Override
public void func() {
System.out.println("我是内部类,且重写了func这个方法!");
}
};
}
}
4.2、变量捕获
public class Lambda04 {
public static void main(String[] args) {
//lambda表达式外部定义一个变量
final int val=100;
NoParameterNoReturn noParameterNoReturn=()->{
System.out.println("捕获变量"+val);
};
noParameterNoReturn.test();
}
}
5、Lambda在集合中的应用
List接口,Map接口:
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class Lambda06 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("trigger");
list.add("nutrition");
list.add("provision");
list.add("nuisance");
//用new 一个接口创建一个匿名内部类的方式
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("========Lambda========");
list.forEach((s)->{
System.out.println(s);
});
//sort
System.out.println("===========sort()===========");
//升序排列
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
//打印
list.forEach((s)->{
System.out.println(s);
});
System.out.println("========Lambda========");
list.sort((o1,o2)->{
return o2.compareTo(o1);
});
//打印
list.forEach((s)->{
System.out.println(s);
});
//Map
System.out.println("===========Map==========");
Map<Integer,String> map=new HashMap<>();
map.put(1,"trigger");
map.put(2,"nutrition");
map.put(3,"provision");
map.put(4,"nuisance");
//用new的方式去实现
map.forEach(new BiConsumer<Integer, String>() {
@Override
public void accept(Integer integer, String s) {
System.out.println("key = " + integer + ", value = " + s);
}
});
System.out.println("========Lambda========");
map.forEach((key,value)->{
System.out.println("key = " + key + ", value = " + value);
});
}
}