活着努力干,死了无遗憾!
- Lambda表达式
- 函数式接口
- 方法引用
一、Lambda表达式
1、什么是Lambda
Lambda表达式是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使得Java语言表达能力得到了提升。Java8中引入了一个新的操作符” -> ”该操作符称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分为两部分:
左侧:Lambda表达式的参数列表。对应接口中抽象方法的参数列表。
右侧:Lambda表达式中所需要执行的功能,即Lambda体。对应接口中抽象方法的实现。
([参数列表])->{
方法的实现}
Lambda可以看作一个简化版的实现了接口的一个匿名内部类,但是这个只类有一个方法
2、Lambda表达式基础语法
Lambda表达式对应接口中的抽象方法(接口中只能有一个抽象方法)。
2.1、无参无返
public class Test {
public static void main(String[] args) {
A a = ()->{
System.out.println("无参无返");
};
a.a1();
}
}
interface A{
void a1();
}
运行结果 |
---|
无参无返 |
2.2、无参有返
生成一个0-9的随机数
public class Test {
public static void main(String[] args) {
A a = ()->{
return (int)(Math.random()*10);
};
System.out.println(a.a1());;
}
}
interface A{
int a1();
}
运行结果 |
---|
8 |
2.3、有参无返
判断一个数是不是偶数
public class Test {
public static void main(String[] args) {
A a = (int i)->{
System.out.println(i%2==0);
};
a.a1(6);
a.a1(7);
}
}
interface A{
void a1(int i);
}
运行结果 |
---|
true false |
2.4、有参有返
计算两个数的乘积
public class Test {
public static void main(String[] args) {
A a = (int i,int j)->{
return i*j;
};
System.out.println(a.a1(6,7));
}
}
interface A{
int a1(int i,int j);
}
运行结果 |
---|
42 |
3、Lambda表达式的省略
-
Lambda表达式的参数列表类型可以省略不写
public class Test { public static void main(String[] args) { A a = (i)->{ // 参数类型可以省略不写 System.out.println(i%2==0); }; a.a1(6); } }
-
如果实现的方法只有一条语句,则大括号可以省略不写
public class Test { public static void main(String[] args) { A a = ()->System.out.println("无参无返"); a.a1(); } }
-
如果实现的方法(需要返回值的方法)只有一条语句,那么
return
语句也可以省略public class Test { public static void main(String[] args) { A a = ()->(int)(Math.random()*10); System.out.println(a.a1());; } }
4、Lambda表达式当作参数使用
public class Test {
public static void main(String[] args) {
System.out.println(aa(5,6,(i,j)->i*j));
}
static int aa(int i, int j, A a){
return a.a1(i,j);
}
}
interface A{
int a1(int i,int j);
}
运行结果 |
---|
30 |
逐步分析:System.out.println(aa(5,6,(i,j)->i*j));
(i,j)->i*j
- 这是一个省略了参数类型,大括号和
return
关键字的Lambda表达式 - 表示有两个参数,分别为
i
和j
,然后返回i*j
的值
- 这是一个省略了参数类型,大括号和
aa(5,6,(i,j)->i*j)
- 调用的下面的静态方法
aa
- 传入了三个参数,5、6和一个Lambda表达式
- 调用的下面的静态方法
System.out.println(aa(5,6,(i,j)->i*j));
- 接收
aa
方法的返回值并打印
- 接收
二、函数式接口
1、什么是函数式接口
一个接口中如果只有一个抽象方法则称为函数式接口
使用注解@FunctionalInterface
修饰接口,则表示该接口是一个函数式接口。
Lambda表达式需要函数式接口的支持
2、函数式接口的使用
就是自己定义一个接口,接口中只有一个抽象方法。上面的Lambda表达式基础语法里的接口A
,就是函数式接口。只不过没有用注解修饰
public class Test {
public static void main(String[] args) {
A<Integer, Integer> a = (i)->{
return i*i;
};
System.out.println(a.a1(6));
}
}
@FunctionalInterface
interface A<T, R>{
T a1(R r);
}
运行结果 |
---|
36 |
3、四大内置函数式接口
就是系统提供的四个内置的函数式接口
3.1、Consumer<T>(消费型接口)
传入一个指定类型参数,没有返回值
传入一个数,打印概述乘以10后的结果
public class Test1 {
public static void main(String[] args) {
Consumer<Integer> c = i->System.out.println(i*10);
c.accept(5);
}
}
运行结果 |
---|
50 |
3.2、Supplier<T>(供给型接口)
不传入参数,T代表返回值类型
返回0-9的随机数
public class Test1 {
public static void main(String[] args) {
Supplier<Integer> s = ()->(int)(Math.random()*10);
System.out.println(s.get());
}
}
运行结果 |
---|
6 |
3.3、Function<T,R>(函数型接口)
传入一个类型的参数
T代表参数类型,R代表返回类型
返回一个数的平方
public class Test1 {
public static void main(String[] args) {
Function<Integer, Integer> f = i->i*i;
System.out.println(f.apply(10));
}
}
运行结果 |
---|
100 |
3.4、Predicate<T>(断言型接口)
传入一个指定类型的参数,返回boolean类型
判断一个数是不是偶数
public class Test1 {
public static void main(String[] args) {
Predicate<Integer> p = i->i%2==0;
System.out.println(p.test(5));
}
}
运行结果 |
---|
false |
三、方法引用
如果Lambda表达式要实现的方法,已经实现了,可以通过方法引用调用
Tips:函数式接口的返回值和参数列表要和方法的返回值和参数列表保持一致
1、对象名::实例方法名
1.1、无参无返
public class Test2 {
public static void main(String[] args) {
ABC abc = new AB()::a1;
abc.ac();
}
}
interface ABC{
void ac();
}
class AB{
void a1(){
System.out.println("啊哈哈哈");
}
}
运行结果 |
---|
啊哈哈哈 |
1.2、无参有返
public class Test2 {
public static void main(String[] args) {
ABC abc = new AB()::a1;
System.out.println(abc.ac());;
}
}
interface ABC{
String ac();
}
class AB{
String a1(){
return "啊哈哈哈";
}
}
运行结果 |
---|
啊哈哈哈 |
1.3、有参无返
public class Test2 {
public static void main(String[] args) {
ABC abc = new AB()::a1;
abc.ac("啊哈哈哈");
}
}
interface ABC{
void ac(String str);
}
class AB{
void a1(String str){
System.out.println(str);
}
}
运行结果 |
---|
啊哈哈哈 |
1.4、有参有返
public class Test2 {
public static void main(String[] args) {
ABC abc = new AB()::a1;
System.out.println(abc.ac("啊哈哈哈"));
}
}
interface ABC{
String ac(String str);
}
class AB{
String a1(String str){
return str;
}
}
运行结果 |
---|
啊哈哈哈 |
2、类::静态方法名
参照上述,将不在一一介绍有没有返回值有没有参数
public class Test2 {
public static void main(String[] args) {
ABC abc = AB::a1;
abc.ac();
}
}
interface ABC{
void ac();
}
class AB{
static void a1(){
System.out.println("啊哈哈哈");
}
}
运行结果 |
---|
啊哈哈哈 |
3、类::实例方法名
public class Test {
public static void main(String[] args) {
AB<A,String> ab = A::a1;
ab.a1(new A(),"啊哈哈哈");
}
}
class A{
void a1(String str){
System.out.println(str);;
}
}
class B{
}
interface AB<T,L>{
void a1(T t,L l);
}
运行结果 |
---|
啊哈哈哈 |
妈的,这个卡了我半天
Tips:第一个参数是实例方法的调用者,第二个参数是实例方法的参数,才能使用该方法引用
A
类里面有一个a1
方法,该方法需要一个参数,参数类型为String
那么,第一个参数就是a1
方法的调用者,想要调用a1
方法,就需要A
类的实例对象,所以参数为A
类的实例对象。new A()
。
第二个参数就是a1
方法的参数了,传入一个String
类型字符串或者String
类型的对象
四、构造器引用
public class Test {
public static void main(String[] args) {
A<String,Integer,Boolean> a = AB::new;
a.a1("张三",20,true);
}
}
interface A<T,A,S>{
void a1(T t,A a,S s);
}
class AB{
public AB(String name,int age,boolean sex) {
System.out.println(name);
System.out.println(age);
System.out.println(sex);
}
}
运行结果 |
---|
张三 20 true |
Tips:构造器的参数列表要和函数式接口的参数列表保持一致