Java8-Lambda表达式
记录个人学习过程,参考https://www.bilibili.com/video/BV1ci4y1g7qD?p=1,侵删
通过Lambda表达式可以替代以前常写的匿名内部类来实现接口,Lambda表达式本质上是一个匿名函数。
入门实例
package com.company;
public class Program {
public static void main(String[] args) {
/**不使用lambda表达式
* */
// Cal c = new Cal() {
// @Override
// public int add(int a, int b) {
// return a+b;
// }
// };
/** 使用lambda表达式
* ()为参数列表
* {}为方法体
*/
Cal c = (int a,int b) -> {return a+b;};
System.out.println(c.add(2,3));
}
interface Cal{
int add(int a,int b);
}
}
Lambda表达式语法
这个Lambda表达式:
(int a,int b) -> {return a+b;}
本质上是一个函数,而
一般的函数类似
int add(int a,int b){
return a+b;
}
一般的函数有返回值,方法名,参数列表,方法体
而Lambda表达式只有参数列表和方法体
说明:
()
:用于描述参数列表
{}
:用于描述方法体
->
:Lambda运算符,可以叫做箭头符号,或goes to
Lambda表达式语法实例
package com.company;
public class Program2 {
public static void main(String[] args) {
If1 if1 = ()->{
System.out.println("无参数无返回值");
};
if1.test();
If2 if2 = (int a)->{
System.out.println("单个参数无返回值,a:"+a);
};
if2.test(12);
If3 if3 = (int a,int b)->{
System.out.println("两个参数无返回值,a+b:"+(a+b));
};
if3.test(12,3);
If4 if4 = ()->{
return 1;
};
System.out.println("无参数有返回值"+if4.test());
If5 if5 = (int a)->{
return a;
};
System.out.println("单个参数有返回值"+if5.test(25));
If6 if6 = (int a,int b)->{
return a+b;
};
System.out.println("两个参数有返回值"+if6.test(25,37));
}
interface If1{
/**无参数无返回值
* */
void test();
}
interface If2{
/**单个参数无返回值
* */
void test(int a);
}
interface If3{
/**两个参数无返回值
* */
void test(int a,int b);
}
interface If4{
/**无参数有返回值
* */
int test();
}
interface If5{
/**单个参数有返回值
* */
int test(int a);
}
interface If6{
/**两个参数有返回值
* */
int test(int a,int b);
}
}
Lambda表达式精简语法
注意点:
- 参数类型可以省略
- 若只有一个参数,()可以省略
- 若方法体只有一条语句,{}可以省略
- 若方法体中唯一的语句是return返回语句,则省略大括号的同时也要省略return
package com.company;
public class Program3 {
public static void main(String[] args) {
If1 if1 = ()-> System.out.println("无参数无返回值");
if1.test();
If2 if2 = a->System.out.println("单个参数无返回值,a:"+a);
if2.test(12);
If3 if3 = ( a,b)->System.out.println("两个参数无返回值,a+b:"+(a+b));
if3.test(12,3);
If4 if4 = ()-> 1;
System.out.println("无参数有返回值"+if4.test());
If5 if5 = a->a;
System.out.println("单个参数有返回值"+if5.test(25));
If6 if6 = (a,b)->a+b;
System.out.println("两个参数有返回值"+if6.test(25,37));
}
interface If1{
/**无参数无返回值
* */
void test();
}
interface If2{
/**单个参数无返回值
* */
void test(int a);
}
interface If3{
/**两个参数无返回值
* */
void test(int a,int b);
}
interface If4{
/**无参数有返回值
* */
int test();
}
interface If5{
/**单个参数有返回值
* */
int test(int a);
}
interface If6{
/**两个参数有返回值
* */
int test(int a,int b);
}
}
方法引用
当多个Lambda表达式的实现函数是一样的时候,可以封装成通用方法,以便于维护;
用方法引用实现:
语法如下:
对象::方法
如果是static方法可以直接 类名::方法
package com.company;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
public class Program4 {
public static void main(String[] args) {
If5 if5 = Program4::testB;
System.out.println("testB:"+if5.test(6));
Program4 program4 = new Program4();
If5 if51 = program4::testA ;
System.out.println("testA:"+if51.test(9));
}
public int testA(int a){
return a-2;
}
public static int testB(int a){
return a-2;
}
interface If5{
/**单个参数有返回值
* */
int test(int a);
}
}
构造方法引用
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
语法:类名::new
实例:
package com.company;
public class Program5 {
public static void main(String[] args) {
//DogService1 dogService1 = ()->new Dog();
//System.out.println(dogService1.getDog());
DogService1 dogService11 = Dog::new;
System.out.println(dogService11.getDog());
DogService2 dogService2 = Dog::new;
System.out.println(dogService2.getDog("Tom",2));
}
interface DogService1{
Dog getDog();
}
interface DogService2{
Dog getDog(String name, int age);
}
}
综合实例
package com.company;
import java.util.ArrayList;
import java.util.List;
public class Program6 {
public static void main(String[] args) {
List<Dog> list = new ArrayList<>();
list.add(new Dog("a",4));list.add(new Dog("f",3));
list.add(new Dog("b",1));list.add(new Dog("e",4));
list.add(new Dog("c",2));list.add(new Dog("d",2));
System.out.println("lambda表达式集合排序");
list.sort(((o1, o2) -> {return o1.getAge()- o2.getAge();}));
// System.out.println(list);
list.forEach(System.out::println);
}
}
@FunctionalInterface注解
前面我们会发现Consumer接口,Comparator接口都有
@FunctionalInterface注解;
这个注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是在这个
接口里面只能有一个抽象方法。
这种类型的接口也称为SAM接口,即Single Abstract Method interfaces
特点
- 接口有且仅有一个抽象方法
- 允许定义静态方法
- 允许定义默认方法
- 允许java.lang. Object中的public方法
- 该注解不是必须的,如果一个接口符合”函数式接口"定义,那么加不加该注解都没有影
响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加
上了@FunctionInterface , 那么编译器会报错
package com.company;
//正确的函数式接口
@FunctionalInterface
public interface TestInterface {
//抽象方法
public void sub();
// java.lang.Object中的pub1ic方法
public boolean equals(Object var1);
//默认方法
public default void defaultMethod() {
}
//静态方法
public static void staticMethod() {
}
}
//错误的函数式接口(有多个轴象方法)
@FunctionalInterface
public interface TestInterface2{
void add();
void sub();
}
系统内置函数式接口
Java8的推出,是以Lambda重要特性,一起推出的,其中系统内置了一系列函数式接口
在jdk的java . util.function包下,有一系列的内置函数式接口
Java内置的四大核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
Supplier供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get() |
Function<T,R>函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法: R apply(T t) |
Predicate断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t) |