Java8 Lambda表达式

71 阅读3分钟

简介

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

匿名内部类

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

        TreeSet<Integer> integers = new TreeSet<>(com);
    }

Lambda表达式

    @Test
    public void test02(){
        Comparator<Integer> com = (a,b) -> Integer.compare(a ,b);

        TreeSet<Integer> integers = new TreeSet<>(com);
    }

基础语法

1.操作符 ->

2.箭头左侧 参数列表

3.箭头右侧 执行代码块/Lambda体

口诀:

1.写死小括号,拷贝右箭头,落地大括号

2.左右遇一括号省

3.左侧推断类型省

语法格式

  • 无参数 无返回值
    @Test
    public void test_noParam_noReturn(){
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello Runnable!");
            }
        };

        Runnable run = () -> System.out.println("Hello Lambda!!!");

        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(run);

        t1.start();
        t2.start();
    }
    
    //执行结果
    //Hello Runnable!
    //Hello Lambda!!!
  • 有一个参数 无返回值
    @Test
    public void test_oneParam_noReturn(){
        Consumer<String> consumer = (a) -> System.out.println(a);
        consumer.accept("我觉得还行!");
		
        //只有一个参数可以省略小括号
        Consumer<String> c1 = a -> System.out.println(a);
        consumer.accept("没有小括号");
    }
  • 有两个及以上的参数,有返回值,并且 Lambda 体中有多条语句
    @Test
    public void test_anyParam_hasReturn(){
       Comparator<Integer> comparator = ((o1, o2) -> {
           System.out.println("这是多行的lambda体");
           return Integer.compare(o1,o2);
       });
    }
  • 有两个及以上的参数,有返回值,并且 Lambda 体中只有1条语句 (大括号 与 return 都可以省略不写)
    @Test
    public void test_anyParam_hasOneReturn(){
        Comparator<Integer> comparator = ((o1, o2) -> Integer.compare(o1,o2));
    }

函数式接口

接口中只有一个抽象方法

@FunctionalIterface 注解可以进行接口校验

    //自定义函数式接口
    package com.test;

    @FunctionalInterface
    public interface MyFunctionalInterface {
        Integer count(Integer a, Integer b);
    }


    @Test
    public void test_functionalInterface1() {
        Integer operation = operation(3, 4, (a, b) -> a * b);
        System.out.println(operation);
    }


    public Integer operation(Integer a, Integer b, MyFunctionalInterface myFun) {
        return myFun.count(a, b);

    }

java 内置四大函数式接口

函数式接口参数类型返回类型用途
Consumer 消费型接口Tvoid对类型为T的对象应用操作:void accept(T t)
Supplier 提供型接口T返回类型为T的对象:T get()
Function<T, R> 函数型接口TR对类型为T的对象应用操作,并返回结果为R类型的对象:R apply(T t)
Predicate 断言型接口Tboolean确定类型为T的对象是否满足某约束,并返回boolean值:boolean test(T t)
  • Consumer
    @Test
    public void test_Consumer(){
        Consumer con = (a) -> Objects.requireNonNull(a);
        con.accept("");
   }
  • Supplier
    @Test
    public void test_Supplier(){
        String s = "supplier";
        Supplier<String> sup = () -> s;
        String s1 = sup.get();
        System.out.println(s1);
    }
  • Function<T, R>
    @Test
    public void test_Function(){
        Function<Integer,Integer> fun = a -> a * 10;

        Integer apply = fun.apply(10);
        System.out.println(apply);
    }
  • Predicate
    @Test
    public void test_Predicate(){
        Predicate predicate = a -> Optional.ofNullable(a).isPresent();
        String s = null;
        boolean test = predicate.test(s);
        System.out.println(test);

    }

其他方法

其他方法

引用

方法的引用

语法格式:
对象 :: 实例方法
类 :: 静态方法
类 :: 实例方法

  • 实例方法的引用
    //对象::实例方法
    @Test
    public void test_ObjectMethod() {
        PrintStream ps = System.out;
        Consumer<String> con = (x) -> ps.println(x);

        con.accept("out");

        Consumer<String> con2 = ps::println;
        con2.accept("in");
    }

注意: Lambda 表达实体中调用方法的参数列表、返回类型必须和函数式接口中抽象方法保持一致

  • 类静态方法引用
    类::静态方法
    @Test
    public void test_classStaticMthod(){
        Comparator<Integer> com1 = (x,y)->Integer.compare(x,y);
        System.out.println(com1.compare(1,2));

        Comparator<Integer> com2 = Integer::compare;

        int compare = com2.compare(1, 2);
        System.out.println(compare);
    }
  • 类实例方法引用
    类::实例方法
    @Test
    public void test_classInstanceMthod(){
        BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);
        System.out.println(bp1.test("a","b"));

        BiPredicate<String, String> bp2 = String::equals;
        boolean test = bp2.test("a", "b");
        System.out.println(test);
    }

条件:Lambda 参数列表中的第一个参数是方法的调用者,第二个参数是方法的参数时,才能使用 ClassName :: Method

构造器引用

语法格式: Class :: new

    @Test
    public void test_ConstructorMethod(){
        Supplier<User> sup = () -> new User();
        Supplier<List> sup1 = ArrayList::new;
    }

注意:需要调用的构造器的参数列表要与函数时接口中抽象方法的参数列表保持一致

数组的引用

语法格式: Type :: new

数组类型的构造器引用的语法比较特殊,我们认为它有一个允许传入int参数的构造器,例子如下:

    @Test
    public void test_Array(){
        Supplier<Integer[]> sup = () -> new Integer[10];
        Supplier<Integer[]> sup1 = Integer[] :: new; //创建失败
    }
    
    @Test
    public void test7(){
        Function<Integer,String[]> fun=x ->new String[x];
        String[] str=fun.apply(3);
        System.out.println(str.length);
        Function<Integer,String[]> fun2=String[]::new;
        String[] str2=fun.apply(4);
        System.out.println(str2.length);
    }

参考文档

深入理解Lambda