Lambda表达式和函数式接口

什么是Lambda表达式

Lambda表达式概述

Lambda表达式是java8中新增的一大亮点,使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。
Lambda是一个匿名函数,我们可以吧Lambda表达式理解为一段可以传递的代表(将代码像数据一样进行传递),
使用它可以写出更简洁,更灵活的代码。作为一种更紧凑的代码风格,Lambda使java的语言表达能力得到了提升。

Lambda表达式的基本使用

格式概述

1.举例:(o1,o2)->Integer.compare(o1,o2)
2.格式:
->:Lambda操作符,或者也可以称作箭头操作符
->左边:可以看做Lambda中的形参列表(其实就是接口中的抽象方法的形参列表)
->右边:Lambda体(其实就是重写的抽象方法的方法体)
3.Lambda表达式的使用:分为六种情况

4.Lambda表达式的本质:作为函数式接口的实例
函数式接口(FunctionalInterface):只声明了一个方法的接口。
该注解@FunctionalInterface可以检查一个接口是否是一个函数式接口。

所以,以前可以用匿名实现类表示的现在都可以用Lambda表达式来写。

Lambda表达式不同情况下的格式

下面使用一段代码来体现Lambda表达式在各种情况下的不同格式:

 @Test
    public void LambdaTest() {

  	//语法格式一:无参,无返回值:	
    //Lambda表达式方式
  	Runnable r2 = () -> System.out.println("无参,无返回值");
  	
 	//语法格式二:Lambda:需要一个参数,但是没有返回值
 	//原本方式
  	Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
    //语法格式二:Lambda:需要一个参数,但是没有返回值    
	Consumer<String> con1 = (String s) -> System.out.println("无参,有返回值");
	
	
	//语法格式三:数据类型可以胜率,因为可由编译器推断得出,称为"类型推断"
	Consumer<String> con2 = (s) -> System.out.println("北京故宫");

	//语法格式四:Lambda若只需要一个参数,则参数的小括号可以省略
	Consumer<String> con3 = s -> System.out.println("一个参数,小括号可以省略");
	
	
    //语法格式五:Lambda 需要两个以上的参数,并且需要返回值
    //原本格式
	Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };
  	 //Lambda 需要两个以上的参数,并且需要返回值
     Comparator<Integer> com2 = (o1, o2)-> {
            return o1.compareTo(o2);
     };
     
    //语法格式六:Lambda只有一条语句时,return与大括号都可以省略
    Comparator<Integer> com2 = (o1, o2) -> o1.compareTo(o2);
}

总结:
->左边:Lambda形参列表的参数类型可以省略,如果参数列表只有一个参数,那么参数的小括号也可以省略;
如果没有参数或有两个以上的时候就不要省略小括号。
->右边:lambda体应该使用一对{}进行包裹,但如果Lambda体只有一条执行语句(这条语句可能是return语句),
可以省略这一对{}和return关键字。注意的是,要么把{}与return一并省略,要么就都不要省略,否则
就会报错。

函数式接口(Function)

什么是函数式接口

函数式接口(FunctionalInterface):只声明了一个方法的接口。
在java中,OOP(面向对象编程)就是一切,但是随着Python等语言的兴起,java 不得不做出调整来适应更加广泛的技术要求,也即java不但可以支持OOP,也可以支持OOF(面向函数编程)。

在函数式编程语言中,Lambda表达式的类型是函数,而在java8中则有所不同,在java8中,Lambda表达式是对象而不是函数,他们必须依附于一类特别的对象类型
-即函数式接口。

简单的说,在java8中,Lambda表达式就是一个函数式接口的实例。这就是函数式接口与Lambda表达式的关系,也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。

可以用@FunctionInterface注解来检测一个接口是否是函数式接口

Java内置四大核心函数式接口

    						 接口名  			   参数类型     返回类型    		方法

消费型接口 Consumer: T void 对类型为T的对象应用操作,包含方法void accept()
供给型接口 Supplier: R 无 返回类型为T的对象,包含方法 T get
函数型接口 Function<T,R> T,R R 对类型为T的对象应用操作,并返回R类型的对象,包含方法 R apply(T t)
段定型接口 Predicate T boolean 确定类型为T的对象是否满足某约束,并返回boolean值,方法,Boolean test(T t)

Lambda表达式中的方法引用

Lambda表达式的方法引用
当传递给Lambda的操作,已经有实现的方法时,就可以使用方法引用
方法引用可以看做Lambda表达式深层次的表达,也就是说,方法引用就是Lambda表达式的一个实例,
通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖

要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型一致(针对情况一和情况二)

格式:使用 :: 来把类(或对象)与方法名分割开来

三种主要使用情况
对象::实例方法名
类::静态方法名
类::实例方法名

方法引用的举例说明

工具类

public class Employee {
    private int age;
    double salary;
    int id;
    String name;
    
	public Employee(){}
	
	public Employee(int id){
	        this.id = id;
    }
    
     public Employee(int age, double salary, int id, String name) {
        this.age = age;
        this.salary = salary;
        this.id = id;
        this.name = name;
    }

    public String getName(){
        return this.name;
    }
}

对象::实例方法名

  @Test
	 //Consumer中的void accept(T t)
	 //PrintStream中的void Println(T t)
	 //以上两个方法都是没有返回值且需要有一个参数的类型,两者需求相同,此种情况下就可以使用方法引用
    public void Test(){
        Consumer<String> con1 = str->System.out.println(str);
        con1.accept("北京");

        System.out.println("***********");

        PrintStream pr = System.out;
        Consumer<String> con2 = pr::println;
        con2.accept("beijing");
    }

类::静态方法

    //Comparator中的int compare(T t1,T t2)
    //Integer中的int compare(T t1,T t2)
    @Test
    public void Test3(){


   //Lambda表达式的方式
   Comparator<Integer> com = (o1,o2)->Integer.compare(o1,o2);
   System.out.println(com.compare(12,20));

   //方法引用的方式
   Comparator<Integer> com1 = Integer::compare;
   System.out.println(com1.compare(12, 20));


    }

情况三:类::实例方法

    @Test
    public void Test4(){
    	//Comparator中的int compare(T t1,T t2)
    	//String中的int t1.compareTo(t2)
    	
        //Lambda表达式方式
        Comparator<String> com = (s1,s2)->s1.compareTo(s2);
        System.out.println(com);//

        System.out.println("**********");

        //方法引用
        //在此例中,由于两者参数类型数量。此时就会将int compare(T t1,T t2)中的t1,当做方法的调用者
        //而将引用方法的类String,放到::的左边
        Comparator<String> com2 = String::compareTo;
        System.out.println(com2.compare("abc", "abm"));


    }

构造器引用和数组引用

构造器引用实例

和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致, 抽象方法的返回值即为构造器对象所属的类型
代码如下:

 //构造器引用
    //supplier中的T get() 与 Employee()都是空参且有返回值,所以可以像方法引用一样使用构造器引用
    @Test
    public void Test1(){

        //Lambda表达式方法
        Supplier<Employee> emp = ()->new Employee();

        System.out.println("**************");

        //构造器引用
        Supplier<Employee> emp1 = Employee::new;

    }
//Function中的R apply(T t)
    @Test
    public void Test2(){


        //Lambda表达式方式
        Function<Integer,Employee> fun = id->new Employee(id);

        //构造器引用方式
        Function<Integer,Employee> fun1 = Employee::new;

    }

数组引用实例

为了方便理解,大家可以把数组看做一个特殊的类,则写法就与构造器引用一致

//数组引用
    @Test
    public void Test5(){

        //Lambda表达式写法
        //Integer用来定义数组长度,String[]代表数组类型
        Function<Integer,String[]> fun = length->new String[length];
        String[] apply = fun.apply(5);
        System.out.println(Arrays.toString(apply));//[null, null, null, null, null]


        //数组引用写法
        Function<Integer,String[]> fun1 = String[]::new;
        String[] apply1 = fun1.apply(5);
        System.out.println(Arrays.toString(apply1));//[null, null, null, null, null]
    }

总结:

Lambda表达式与平时所进行的编程格式有很大的不同,乍一看很容易看晕,但是只要实际上手把每一种情况都敲一下,就很容易了解这种编码方式,了解之后甚至会有停不下来的感觉。希望这个文章有一些帮助吧,希望大佬的指正

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值