(Java学习笔记)JavaSE Lambda表达式

Lambda 表达式为java1.8的新特性,引入的一种新的语法元素和操作符 “->”。

1.为什么使用Lambda表达式

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

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

Lambda表达式的使用举例:

@Test
    public void test1(){

        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("我爱北京天安门");
            }
        };
        r1.run();

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

        Runnable r2 = () -> System.out.println("我爱北京故宫");
        r2.run();
    }

    @Test
    public void test2(){

        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };

        int compare1 = com1.compare(12,21);
        System.out.println(compare1);

        System.out.println("***********************");
        //Lambda表达式的写法
        Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2);

        int compare2 = com2.compare(32,21);
        System.out.println(compare2);

        System.out.println("***********************");
        //方法引用
        Comparator<Integer> com3 = Integer :: compare;

        int compare3 = com3.compare(32,21);
        System.out.println(compare3);
    }

2、Lambda表达式规则

2.1、格式

“->“ : lambda操作符,或箭头操作符

左侧:指定了 Lambda 表达式需要的参数列表 ,(其实就是接口中的抽象方法中的形参列表)(省略形参类型 为类型推断

右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即 Lambda 表达式要执行的功能。(其实就是重写的抽象方法的方法体)

2.2、语法格式

总结:

左边:lambda形参列表的参数类型可省略(类型推断),若lambda形参列表只用一个参数,()可省略

右边:lambda体需使用一对{}包裹,若lambda体只有一条执行语句(可能为return语句),可省略{}和return关键字。

具体语法格式有以下六种:

package com.zck.lambdatest;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * Lambda表达式 本质:作为接口(需为函数式接口)的具体实现对象,即作为函数式接口的实例
 *
 * @author zck
 * @create 2020-04-19 18:37
 */
public class LambdaTest {
    //语法格式一:无参,无返回值
    @Test
    public void test1() {
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("java 使我痛苦");
            }
        };
        r1.run();

        Runnable r2 = () -> System.out.println("使我痛苦者,必使我强大");
        r2.run();
    }

    //语法格式二:Lambda 需要一个参数,但是没有返回值。
    @Test
    public void test2() {
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("天青色等烟雨");

        Consumer<String> consumer1 = (String s) -> System.out.println(s);
//        Consumer<String> consumer1 = System.out::println;
        consumer1.accept("而我在等你");
    }

    //语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
    @Test
    public void test3() {
        Consumer<String> consumer2 = (str) -> System.out.println(str);
        consumer2.accept("月色被打捞起");
    }
    //语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略
    @Test
    public void test4(){
        Consumer<String> consumer3 = str -> System.out.println(str);
        consumer3.accept("晕开了结局");
    }
    //语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
    @Test
    public void test5(){
        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);
            }
        };
        System.out.println(com1.compare(12, 20));

        Comparator<Integer> com2 = (o1,o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };
        System.out.println(com2.compare(20, 12));
    }
    //语法格式六:当 Lambda 体只有一条语句时,return与大括号若有,都可以省略
    @Test
    public void test6(){
        Comparator<Integer> com3 = (o1,o2) -> o1.compareTo(o2);
//        Comparator<Integer> com3 = Integer::compareTo;
        System.out.println(com3.compare(12,12));
    }
}

3、函数式(Functional)接口

定义:只包含一个抽象方法的接口,称为函数式接口。可以通过 Lambda 表达式来创建该接口的对象

可以在一个接口上使用 @FunctionalInterface 注解,检查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

java.util.function包下定义了Java 8 的丰富的函数式接口

Java 内置四大核心函数式接口
在这里插入图片描述

代码举例:

public class LambdaTest2 {

    @Test
    public void test1(){

        happyTime(500, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("学习太累了,去天上人间买了瓶矿泉水,价格为:" + aDouble);
            }
        });

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

        happyTime(400,money -> System.out.println("学习太累了,去天上人间喝了口水,价格为:" + money));
    }

    public void happyTime(double money, Consumer<Double> con){
        con.accept(money);
    }

    @Test
    public void test2(){
        List<String> list = Arrays.asList("北京","南京","天津","东京","西京","普京");

        List<String> filterStrs = filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("京");
            }
        });

        System.out.println(filterStrs);


        List<String> filterStrs1 = filterString(list,s -> s.contains("京"));
        System.out.println(filterStrs1);
    }

    //根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定
    public List<String> filterString(List<String> list, Predicate<String> pre){

        ArrayList<String> filterList = new ArrayList<>();

        for(String s : list){
            if(pre.test(s)){
                filterList.add(s);
            }
        }
        return filterList;

    }
}

4、方法引用与构造器引用

4.1、方法引用(Method References)

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式

接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖

  • 要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的 方法的参数列表和返回值类型保持一致!
  • 格式:使用操作符 “::” 将类(或对象) 与 方法名分隔开来。
    • 对象::实例方法名
    • 类::静态方法名
    • 类::实例方法名

代码举例:

当函数式接口方法的第一个参数是需要引用方法的调用者,并且第二个参数是需要引用方法的参数(或无参数)时:ClassName::methodName

public class MethodReferencesTest {
    @Test
    public void test(){
        Consumer<String> con1 = s -> System.out.println(s);
        con1.accept("你说嘴巴嘟嘟");
		//等价于
        Consumer<String> con2 = System.out :: println;
        con2.accept("dududududu");
    }
    @Test
    public void test2(){
        Comparator<Integer> com1 = (x,y) -> Integer.compare(15,20);
        //等价于
        Comparator<Integer> com2 = Integer :: compare;

    }
    @Test
    public void test3(){
        BiPredicate<String,String> bp = (x,y) -> x.equals(y);
        //等价于
        BiPredicate<String,String> bp1 = String::equals;
        boolean flag = bp1.test("hello", "hi");
        System.out.println(flag);
    }
}

4.2、构造器引用与数组引用

构造器引用格式: ClassName::new

可以把构造器引用赋值给定义的方法,要求构造器参数列表要与接口中抽象 方法的参数列表一致!且方法的返回值即为构造器对应类的对象。

代码举例:

@Test
    public void test1(){
        //Supplier 的  T get();
        //Person 的空参构造器   person()
        Supplier<Person> sup = () -> new Person();
        Person person = sup.get();

        //格式:ClassName::new
        Supplier<Person> sup1 = Person::new;
        Person person1 = sup1.get();
        System.out.println(person1);//Person{age=0, name='null'}

        //Function<T, R>  的 R apply(T t)
        Function<String,Person> fun = name -> new Person(name) ;
        Person person2 = fun.apply("Tom");

        Function<String,Person> fun1 = Person::new;
        Person person3 = fun1.apply("Lucy");
        System.out.println(person3);//Person{age=0, name='Lucy'}

        //BiFunction<T, U, R>  的 R apply(T t, U u)
        BiFunction<Integer,String,Person> biFun = (id,name) -> new Person(id,name);
        Person person4 = biFun.apply(12, "Marry");
        System.out.println(person4);//Person{age=12, name='Marry'}

        BiFunction<Integer,String,Person> biFun1 = Person::new;
        Person person5 = biFun1.apply(20, "Judy");
        System.out.println(person5);//Person{age=20, name='Judy'}
    }

数组引用格式: type[] :: new

代码举例:

    @Test
    public void test2(){
        //Function<T, R>  的 R apply(T t)
        Function<Integer,String[]> fun1 = length -> new String[length];
        String[] arr1 = fun1.apply(5);
        System.out.println(Arrays.toString(arr1));//[null, null, null, null, null]
        
        Function<Integer,String[]> fun2 = String[]::new;
        String[] arr2 = fun2.apply(5);
        arr2[1] = "马云";
        arr2[2] = "马化腾";
        arr2[3] = "刘强东";
        System.out.println(Arrays.toString(arr2));//[null, 马云, 马化腾, 刘强东, null]

    }

注:本文章是根据哔哩哔哩公开课 Java -Java 学习- Java 基础到高级-宋红康-零基础自学Java-尚硅谷 整理所得
大爱康师傅!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值