0%

java-Day16——lambda表达式

Lambda表达式

使用举例

1
Comparator<Integer> com2 =(o1, o2)-> Integer.compare(o1, o2);

格式举例

lambda形参列表 ->Lambda方法体

->:Lambda操作符或箭头操作符

->的左边:lambda形参列表,对应着要重写接口中的抽象方法的形参列表

->的右边:lambda体,对应着接口的实现类要重写的方法的方法体

无参,无返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void test(){
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("xixihaha");
}
};
r1.run();

//Lambda表达式写法
Runnable r2 = () ->{
System.out.println("xixihaha");
};
r2.run();
}

需要一个参数,但无返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("嘻嘻哈哈");

//Lambda表达式写法
Consumer<String> con1 = (String s) ->{
System.out.println(s);
};
con1.accept("嘻嘻哈哈");
}

数据类型可以省略,因为可以推断除了,类型推断

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void test4(){
Consumer<String> con1 = (String s) ->{
System.out.println(s);
};
con1.accept("xixihaha");
//Lambda表达式写法
Consumer<String> con2 = (s) -> {
System.out.println(s);
};
con2.accept("xixihaha");
}

若只需要一个参数,参数小括号可以省略

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void test5(){
Consumer<String> con1 = (String s) ->{
System.out.println(s);
};
con1.accept("xixihaha");
//Lambda表达式写法
Consumer<String> con2 = s -> {
System.out.println(s);
};
con2.accept("xixihaha");
}

两个或以上的参数,多条执行语句,并且有返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void test6(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
//Lambda表达式写法
Comparator<Integer> com2 = (o1,o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
}

当Lambda体只有一条语句时,return与大括号若有,都可以忽略

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void test7(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
//Lambda表达式写法
Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);
}

Lambda表达式本质

  • 一方面,lambda表达式作为接口的实现类的对象。
  • lambda表达式是一个匿名函数

函数式接口

定义:

  • 如果接口中只声明有一个抽象方法,则此接口就称为函数式接口。

  • 只有给函数式接口提供实现类的对象时,我们才可以使用lambda表达式

常见的函数式接口

消费型接口:Consumer void accept(T t)

供给型接口:Supplier T get()

函数型接口: Function<T,R> R apply(T t)

判断型接口:Predicate boolean test(T t)

Lambda表达式的语法规则总结

->的左边:lambda形参列表,参数的类型都可以省略。形参如果只有一个,则一对()也可以省略

->的右边:lambda体,对应着重写的方法的方法体。如果方法体只有一行执行语句,则一对{}省略

方法引用

举例

Integer :: compare

理解

  • 方法引用,可以看作是基于Lambda表达式的进一步刻画
  • 当需要提供一个函数式接口的实例时,我们可以使用lambda表达式提供此实例
    • 当满足一定条件的情况下,我们还可以使用方法引用或构造器替换lambda表达式

本质

方法引用作为函数式接口的实例

格式

类(或对象)::方法名

具体使用情况说明

Case1: 对象::实例方法

要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的形参列表和返回值都一致。此时可以考虑使用方法b实现对方法a的替换和覆盖。此替换或覆盖即为方法应用。

注意:此方法b是非静态的方法,需要对象调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//情况1: 对象::实例方法
//Consumer中的void accept(T t)
//PrinStream中的void println(T t)
@Test
public void test1(){
//1.
Consumer<String> con1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
//2.
Consumer<String> con2 = s -> System.out.println(s);

//3.
Consumer<String> con3 = System.out::println;
con3.accept("hello");
}

//Supplier中的T get()
//Employee中的String getName()
@Test
public void test2(){
//1.
Employee emp = new Emplyoee("alugg",15);
Supplier<String> sup1 = new Supplier<String>() {
@Override
public String get() {
return emp.getName();
}
};
System.out.println(sup1.get());
//2.lambda表达式
Supplier<String> sup2 = ()->emp.getName();
System.out.println(sup2.get());
//3.方法引用
Supplier<String> sup3 = emp::getName;
}

Case2: 类::静态方法

要求:函数式接口中的抽象方法a与其内部实现时调用的类的某个静态方法b的形参列表和返回值都相同(一致)。此时可以考虑使用方法b实现对方法a的替换和覆盖。此替换或覆盖即为方法应用。

注意:此方法b是静态的方法,需要对象调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//Comparator中的int compare(T t1, T t2)
//Integer中的int compare(T t1, T t2)
@Test
public void test3(){
//1.
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
//2.
Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1, o2);
//3.
Comparator<Integer> com3 = Integer::compare;
}

//Function中的R apply(T t)
//Math中的Long round(Double d)
@Test
public void test4(){
//1.
Function<Double, Long> fun1 = new Function<Double, Long>() {
@Override
public Long apply(Double aDouble) {
return Math.round(aDouble);
}
};
//2.
Function<Double,Long> fun2 = aDouble -> Math.round(aDouble);

//3.
Function<Double,Long> fun3 = Math::round;
}

Case3: 类::实例方法

要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的返回值类型相同。

同时,抽象方法a中有n个参数,方法b中有n-1个参数。且抽象方法a的第1个参数作为方法b的调用者,切抽象方法a的后n-1个参数与方法b的n-1个参数类型相同

注意:此方法b是非静态方法,需要对象调用。但是形式上,写出对象a所属的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Test
public void test6(){
//1.
BiPredicate<String, String> biPre1 = new BiPredicate<String, String>() {
@Override
public boolean test(String s, String s2) {
return s.equals(s2);
}
};

//2.
BiPredicate<String, String> biPre2 = (s1,s2) -> s1.equals(s2);

//3.
BiPredicate<String, String> biPre3 = String::equals;
}
@Test
public void test7(){
Employee emp = new Emplyoee("alugg",15);
//1.
Function<Employee, String> fun1 = new Function<Employee, String>() {
@Override
public String apply(Employee employee) {
return employee.getName();
}
};

//2.
Function<Employee, String> fun2 = emp -> emp.getName();

//3.
Function<Employee, String> fun3 = Employee::getName;
}

构造器引用

格式

类名::new

说明

  • 调用了类名对应的类中的某一个确定的构造器
  • 具体调用的是类中的哪一个构造器取决于函数式接口函数式接口的抽象方法的形参列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Test
public void test1(){
Supplier<Employee> sup1 = new Supplier<Employee>(){
@Override
public Employee get(){
return new Employee();
}
};

//2.构造器引用
Supplier<Employee> sup2 = Employee::new;
}

@Test
public void test2(){
//Function 中的R apply(T t)
Function<Integer, Employee> func1 = new Function<Integer, Employee>() {
@Override
public Employee apply(Integer id) {
return new Employee(id);
}
};

//2.
Function<Integer, Employee> func2 = Employee::new;
}

@Test
public void test3(){
BiFunction<Integer, String, Employee> func1 = new BiFunction<Integer, String, Employee>() {
@Override
public Employee apply(Integer id, String name) {
return new Employee(id, name);
}
};

//2.
BiFunction<Integer, String, Employee> func2 = Employee.new;
}

数组引用

1
2
3
4
5
6
7
8
9
10
11
@Test
public void test(){
Function<Integer, Employee[]> func1 = new Function<Integer, Employee[]>() {
@Override
public Employee[] apply(Integer length) {
return new Employee[length];
}
};
//
Function<Integer, Employee[]> func2 = Employee[]::new;
}
-------------本文结束感谢您的阅读-------------