“我正在参与「启航方案」”

Lambd表达式

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

1. 格局

‘->’ :lambda操作符或箭头操作符
‘->’的左面: Lambda形参列表(其实便是接口中的抽象办法的形参列表)
‘->’的右边: Lambda体 (其实便是 重写的抽象办法的办法体)

2. Lambda表达式的运用

Lambda表达式的运用为了便利理解,分为6种情况介绍,经过内置函数式接口来举例,也能够对比匿名函数来理解。

  1. 语法格局一:无参,无回来值,Lambda体只需一条语句
Runnable r2 = ()->{
            System.out.println("Test1");
        };
  1. 语法格局二:Lambda需要一个参数,并且无回来值
Consumer<String> con2 = (String s)->{
            System.out.println(s);
        };
        con2.accept("test2");
  1. 语法格局三:Lambda只需要一个参数时,参数的小括号能够省掉,一起省掉参数变量类型(类型揣度)
Consumer<String> con2 = s->{
            System.out.println(s);
        };
        con2.accept("test2");
  1. 语法格局四:Lambda需要两个参数,并且有回来值
Comparator<Integer> com2 = (Integer o1,Integer o2) -> {
    return o1.compareTo(o2);
};
  1. 语法格局五:当 Lambda 体只需一条语句时,return 与大括号能够省掉
Comparator<Integer> com2 = (Integer o1,Integer o2) -> o1.compareTo(o2);
  1. 语法格局五:数据类型能够省 略,由于可由编译器揣度得出, 称为“类型揣度
// 数据类型能够省掉,由于可由编 译器揣度得出, 称为“类型揣度
Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);

上述 Lambda 表达式中的参数类型都是由编译器揣度得出的。Lambda 表达式中无需指定类型,程序仍然能够编译,这是由于 javac 根据程序的上下文,在后台揣度出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器揣度出来的。这便是所谓的“类型揣度”

3. 函数式接口

3.1 什么是函数式接口

只包括一个抽象办法的接口,称为函数式接口。

你能够经过 Lambda 表达式来创建该接口的目标。(若 Lambda 表达式抛出一个受检反常,那么该反常需要在目标接口的抽象办法上进行声明)。Lambda表达式也是依赖于函数式接口的。

我们能够在恣意函数式接口上运用 @FunctionalInterface 注解, 这样做能够检查它是否是一个函数式接口,一起javadoc也会包括一条声明,阐明这个接口是一个函数式接口。

3.2 如何理解函数式接口

1.Java从诞生口起便是一向倡导“全部皆目标”,在Java里面面向目标(OOP)编程是全部。但是随着python、 scala等语言的兴起和新技能的挑战,Java不得不做出调整以便支持更加广泛的技能要求,也即Java不但能够支持OOP还能够支持OOF(面向函数编程)

2.在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在Java8中,Lambda表达式是目标,而不是函数,它们必须依附于一类特别的目标类型-函数式接口。

3.简略的说,在Java8中,Lambda表达式便是一个函数式接口的实例。这便是Lambda表达式和函数式接口的联系。也便是说,只需一少目标是函数式接口的实例,那么该目标就能够用Lambda表达式来表示。

所以曾经用匿名实现类表示的现在都能够用Lambda表达式来写。

3.3 自定义函数式接口

/**
这个接口里只能写一个办法,写多个办法注解会爆红,注解的作用是验证该接口是否是函数接口
若果不写该注解,并且接口只需一个办规律该接口也是函数式接口
*/
@FunctionalInterface  
public interface MyInterface { 
    void method();
}
//泛型写法
@FunctionalInterface  
public interface MyInterface<T> { 
    T method(T t);
}

3.4 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);

举两个简略的比如

public void test4(){
        Consume(500, new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println("消费了"+integer);
            }
        });
        //lambda表达式写法
        Consume(400,money-> System.out.println("赚了"+money));
    }
public static void Consume(int money, Consumer<Integer> consumer){
        consumer.accept(money);
}
public void test5(){
        List<String> list = Arrays.asList("sss","rrr","yyyyy","ssdasds","sd");
        list = predit(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length()>3;
            }
        });
        System.out.println(list.toString());
    	//lambda表达式写法
        List<String> list1 = Arrays.asList("12","13","14","15","16","17");
        list1 = predit(list1,i->Integer.parseInt(i)>14);
        System.out.println(list1.toString());
    }
    public static List<String> predit(List<String> strings, Predicate<String> predicate){
        List<String> list = new ArrayList<>();
        for (String s:strings){
            if (predicate.test(s)){
                list.add(s);
            }
        }
        return list;
    }

下篇预告:Stream常用的API,欢迎持续交流学习