Lambda是什么
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性,Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),使用 Lambda 表达式可以使代码变的更加简洁紧凑。
Lambda是一个匿名函数
()->{}
():描述参数列表;{}:用来描述方法体
->:lambda运算符,称作 goes to
函数式接口
说到Lambda就不得不说函数式接口
什么是函数式接口?
- 只包含一个抽象方法的接口,称为函数式接口。
- 可以通过Lambda表达式来创建该接口的对象(若Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)
- 在Java8后可以在任意函数式接口上使用@FunctionalInterface注解,其主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。
@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
void test(int a,int b);
}
Lambda的使用条件
从以上能够看出,Lambda的使用条件是接口中有且只有一个必须实现的方法,如果有一个以上,Lambda就不知道该实现那个方法,在java8中新增了接口的默认方法,Lambda不受其影响
默认方法:
@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
void test(int a,int b);
default void test(){
System.out.println("默认方法");
}
}
Lambda的使用
先创建六个接口来分别测试
@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
void test(int a,int b);
default void test(){
System.out.println("默认方法");
}
}
-----
@FunctionalInterface
public interface LambdaNoneReturnNoneParm {
void test();
}
-----
@FunctionalInterface
public interface LambdaNoneReturnSingleParm {
void test(int a);
}
-----
@FunctionalInterface
public interface LambdaSingleReturnMutipleParm {
int test(int a,int b);
}
-----
@FunctionalInterface
public interface LambdaSingleReturnNoneParm {
int test();
}
-----
@FunctionalInterface
public interface LambdaSingleReturnSingleParm {
int test(int a);
}
Lambda表达式的基础语法
//1.Lambda表达式的基础语法
//无参无返回
LambdaNoneReturnNoneParm lambda1 = ()->{
System.out.println("LambdaNoneReturnNoneParm");
};
lambda1.test();
//单个参数,无返回
LambdaNoneReturnSingleParm lambda2 = (int a)->{
System.out.println("LambdaNoneReturnSingleParm: "+a);
};
lambda2.test(77);
//多个参数,无返回
LambdaNoneReturnMutipleParm lambda3 = (int a,int b)->{
System.out.println("LambdaNoneReturnMutipleParm: a:"+a+",b: "+b+",a+b: "+(a+b));
};
lambda3.test(10,77 );
//无参,有返回
LambdaSingleReturnNoneParm lambda4 = ()->{
return 77;
};
int ret = lambda4.test();
System.out.println(ret);
//单个参数,有返回
LambdaSingleReturnSingleParm lambda5 = (int a)->{
return a*10;
};
int ret2 = lambda5.test(7);
System.out.println(ret2);
//多个参数,有返回
LambdaSingleReturnMutipleParm lambda6 = (int a,int b)->{
return a*b;
};
int ret3 = lambda6.test(7,11);
System.out.println(ret3);
Lambda语法精简
- 参数类型,由于已经在接口的抽象方法中,已经定义了参数的数量和类型,所以在表达式中,参数的类型可以省略(参数类型要么都省略,要么都不省略,不能只省略其中一个)
//多个参数,无返回
LambdaNoneReturnMutipleParm lambda = (a,b)->{
System.out.println("LambdaNoneReturnMutipleParm: a:"+a+",b: "+b+",a+b: "+(a+b));
};
lambda.test(10,77 );
- 参数小括号,如果参数的数量只要一个,小括号可以省略
//单个参数,无返回
LambdaNoneReturnSingleParm lambda2 = a->{
System.out.println("LambdaNoneReturnSingleParm: "+a);
};
lambda2.test(77);
- 方法大括号,如果方法体中只有一条语句,大括号可以省略
//无参无返回
LambdaNoneReturnNoneParm lambda3 = ()-> System.out.println("LambdaNoneReturnNoneParm");
lambda3.test();
- 如果方法体中,唯一的一条语句是返回语句,在省略大括号的同时必须省略掉return
LambdaSingleReturnNoneParm lambda4 = ()-> 77;
int ret = lambda4.test();
System.out.println(ret);
lambda语法进阶
- 方法引用:可以快速的将一个lambda表达式的实现指向一个已经实现的方法
语法;方法的属于者::方法名
参数类型和数量要和接口中的方法一致,返回值也一样
静态方法引用:
public class syntax3 {
public static void main(String[] args) {
//lambda语法进阶
//方法引用:可以快速的将一个lambda表达式的实现指向一个已经实现的方法
//语法,方法的属于者::方法名
//参数类型和数量要和接口中的方法一致,返回值也一样
// LambdaSingleReturnSingleParm lambda1 = a -> a*2;
// LambdaSingleReturnSingleParm lambda2 = a -> a*2;
LambdaSingleReturnSingleParm lambda1 = a -> change(a);
int ret = lambda1.test(2);
System.out.println("ret: "+ret);
//方法引用
LambdaSingleReturnSingleParm lambda2 = syntax3::change;
int ret2 = lambda2.test(2);
System.out.println("ret2: "+ret2);
}
private static int change(int a){
return a*2;
}
}
构造方法的引用:
先定义一个Person类
public class Person {
private String name;
private int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person() {
System.out.println("无参构造器");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参构造器: "+name+",age: "+age);
}
}
PersonCreater creater = ()->new Person();//一般的Lambda用法
Person a = creater.getPerson();
//无参构造方法的引用
PersonCreater creater1 = Person::new;//构造方法引用
Person b =creater1.getPerson();
//多个参数构造方法引用
PersonCreaterWithParm creater2 = Person::new;
Person c = creater2.getPerson("林北",21 );
-----
@FunctionalInterface
interface PersonCreater{
Person getPerson();
}
@FunctionalInterface
interface PersonCreaterWithParm{
Person getPerson(String name,int age);
}
Java四大核心函数式接口
在使用Lambda表达式的时候总要自己写函数式接口吗? 当然不是这样了,Java8里面提供了四大核心的函数式供我们使用
函数式接口 | 参数类型 | 返回类型 | 作用 |
---|---|---|---|
Consumer | T | void | 对类型T参数操作,无返回结果,包含方法 void accept(T t) |
Supplier | 无 | T | 返回T类型参数,方法时 T get() |
Function | T | R | 对类型T参数操作,返回R类型参数,包含方法 R apply(T t) |
Predicate | T | Boolean | 断言型接口,对类型T进行条件筛选操作,返回boolean,包含方法 boolean test(T t) |
使用
/**
* Consumer<T>
*/
@Test
public void ConsumerTest(){
consumer("Consumer",(m)-> System.out.println("我是ConsumerTest接口:"+m) );
}
public void consumer(String name, Consumer consumer){
consumer.accept(name);
}
/**
* Supplier<T>
*/
@Test
public void SupplierTest() {
List<Integer> list = getNumList(7,()->(int)Math.random()*8);
list.forEach(System.out::println);
}
public List<Integer> getNumList(int n, Supplier<Integer> supplier){
List<Integer> list = new ArrayList<>();
for(int i = 0;i<n;i++){
Integer num = supplier.get();
list.add(num);
}
return list;
}
/**
* Function<T,R>
*/
@Test
public void FunctionTest(){
String str=strHandle("Hello World",(string)->string.substring(2,5 ));
System.out.println(str);
}
public String strHandle(String str, Function<String,String> fun){
return fun.apply(str);
}
/**
* Predicate<T>
*/
@Test
public void PredicateTest(){
List<String> list1= Arrays.asList("Predicate","Function","Supplier","Consumer");
List<String> list=filterList(list1,(s)->s.length()>8);
for (String s : list) {
System.out.println(s);
}
}
public List<String> filterList(List<String> list, Predicate<String> predicate){
List<String> strings=new ArrayList<>();
for (String string : list) {
if(predicate.test(string)){
strings.add(string);
}
}
return strings;
}