💕"我不要麻木的死去"💕
作者:Mylvzi
文章主要内容:Java中lambda表达式的使用
一.背景
lambda表达式是Java SE 8中一个重要的新特性,允许你使用一个表达式来代替功能接口。lambda表达式可以看作一个没有返回值,没有修饰符修饰的方法,它具有参数和这些参数的主体(方法体)Lambda 表达式(Lambda expression),基于数学中的λ演算得名,也可称为闭包(Closure)
二.语法
1.基本语法
基本语法: (parameters) -> expression 或 (parameters) ->{ statements;
- parameters:类似于方法中的形参列表,参数来源于函数式接口的参数
- ->:可以理解为"被用于"
- expression :方法体 可以是一条语句也可以是多条语句
2.函数式接口
函数式接口就是只含有一条抽象方法的接口
如果接口上声明了@FunctionalInterface,那么编译器就会按照函数式接口进行检验,也即此接口内部只能有一个抽象方法,但是可以使用default来添加一个非抽象方法
@FunctionalInterface
interface FuncInterface1 {
void test();
}
// 这样也是可以的
@FunctionalInterface
interface FuncInterface2 {
void test();
default void test2(){
System.out.println("===");
}
}
三.lambda表达式的基本使用
lambda表达式就相当于使用一种更简单的方式重写了抽象方法(相比于使用匿名内部类)
1.无返回值,无参数
//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
使用两种方式实现
// 使用lambda表达式重写函数式接口的抽象方法 参数 方法体
NoParameterNoReturn noParameterNoReturn1 = () -> System.out.println("hello1");
noParameterNoReturn1.test();// 输出hello1
// 使用匿名内部类重写函数式接口的抽象方法
NoParameterNoReturn noParameterNoReturn2 = new NoParameterNoReturn() {
@Override
public void test() {
System.out.println("hello2");
}
};
2.无返回值,一个参数
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
}
使用两种方式实现
// 使用lambda表达式
OneParameterNoReturn oneParameterNoReturn = (x) -> System.out.println(x);
oneParameterNoReturn.test(10);// 打印10
// 使用匿名内部类
OneParameterNoReturn oneParameterNoReturn1 = new OneParameterNoReturn() {
@Override
public void test(int a) {
System.out.println(a);
}
};
注意:当参数只有一个或者方法体只有一句时,可以省略外面的();
3.无返回值多个参数
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a,int b);
}
使用两种方式实现
// 使用lambda表达式
MoreParameterNoReturn moreParameterNoReturn = (x,y) -> System.out.println(x+y);
moreParameterNoReturn.test(10,20);// 输出30
// 使用匿名内部类
MoreParameterNoReturn moreParameterNoReturn1 = new MoreParameterNoReturn() {
@Override
public void test(int a, int b) {
System.out.println(a+b);
}
};
4.有返回值无参数
//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
int test();
}
使用两种方式实现
NoParameterReturn noParameterReturn = () -> {return 10;};
System.out.println(noParameterReturn.test());// 输出10
// 简化
NoParameterReturn noParameterReturn1 = () ->10;
System.out.println(noParameterReturn1.test());// 输出10
// 使用匿名内部类
NoParameterReturn noParameterReturn2 = new NoParameterReturn() {
@Override
public int test() {
return 10;
}
};
5.有返回值一个参数
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
int test(int a);
}
使用两种方式实现
OneParameterReturn oneParameterReturn = (x) -> {return x*x;};
System.out.println(oneParameterReturn.test(10));// 输出100
// 简化
OneParameterReturn oneParameterReturn1 = x -> x*x;
System.out.println(oneParameterReturn1.test(10));// 输出100
// 使用匿名内部类
OneParameterReturn oneParameterReturn2 = new OneParameterReturn() {
@Override
public int test(int a) {
return a*a;
}
};
6.有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a,int b);
}
使用两种方式实现
MoreParameterReturn moreParameterReturn = (x,y) -> {return x+y;};
System.out.println(moreParameterReturn.test(10, 20));// 输出30
// 使用匿名内部类
MoreParameterReturn moreParameterReturn1 = new MoreParameterReturn() {
@Override
public int test(int a, int b) {
return a+b;
}
};
四.在优先级队列中的使用
优先级队列中往往涉及到比较,我们在实例化优先级队列的时候往往要传递一个比较器,规定比较的对象
// 使用匿名内部类实现Comparator接口
PriorityQueue<Integer> priorityQueue = new PriorityQueue(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
其实也能看出,Comparator方法应该是一个函数式接口,它属于"多个参数,有返回值"的类型(对应于上面的最后一种情况),此处就可以使用lambda表达式进行语法上的精简
// 使用lambda表达式实现优先级队列中的比较
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1,o2) ->{return o1-o2;});
Comparator的源码 -->多个参数,有返回值的接口
五.创建线程
创建线程的方式有很多种,可以采用匿名内部类,lambda表达式
1.匿名内部类创建线程
// 创建线程 ->使用匿名内部类
Thread thread1 = new Thread() {
@Override
public void run() {
System.out.println("hello thread");
}
};
// 这种方式可以降低耦合性(推荐)
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello thread2");
}
});
为什么可以使用匿名内部类创建一个线程呢?主要是因为Thread类实现了Runnable接口,这个接口是一个函数式接口,只有一个抽象方法run()
2.使用lambda表达式
既然Thread可以通过匿名内部类方式创建线程,同时就可以使用lambda表达式来简化创建
// 方式1
Thread thread1 = new Thread(() ->{
System.out.println("hello thread1");
});
thread1.run();// 输出hello thread1
//方式2 利用lambda表达式实例化一个runnable接口 降低耦合性
Runnable runnable = () -> System.out.println("hello thread2");
Thread thread2 = new Thread(runnable);
thread2.run();// 输出hello thread2