JDK8 之 Lambda 总结

一. 简介

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

二. 使用效果

2.1 未使用 lambda 和 使用 lambda 的区别

/** * 未使用 lambda 表达式 */
    @Test
    public void test01() {

        Comparator<Integer> comparator1 = new Comparator<Integer>() {

            @Override
            public int compare(Integer o1, Integer o2) {

                return Integer.compare(o1,o2);
            }
        };
        TreeSet set = new TreeSet(comparator1);


    }

    /** * 使用 lambda 表达式 */
    @Test
    public void test02() {

        // 使用 lambda
        Comparator<Integer> comparator = (o1,o2) -> Integer.compare(o1,o2);
        TreeSet set = new TreeSet(comparator);

    }

三. 基本语法

Lambda 表达式在Java 语言中引入了一个新的语法元 素和操作符。这个操作符为 “->” , 该操作符被称 为 Lambda 操作符或剪头操作符。它将 Lambda 分为 两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能。

// 语法格式一: 无参, 无返回值, lambda 体只需要执行一条语句
        Runnable runnable = () -> System.out.println("hello world");

        // 语法格式二: 有一个参数, 并且无返回值
        Consumer<String> consumer = (args) -> System.out.println(args);

        // 语法格式三: 只有一个参数时,参数的小括号可以省略
        Consumer<String> consumer2 = args -> System.out.println(args);

        // 语法格式四: lambda 需要两个参数,多行执行语句,并且有返回值
        Comparator<Integer> comparator = (a, b) -> {
            System.out.println("hello world");
            return Integer.compare(a, b);
        };

        // 语法格式五: lambda 需要两个参数,一条执行语句,并且有返回值
        Comparator<Integer> comparator2 = (a, b) -> Integer.compare(a, b);

        // 语法格式六: lambda 表达式的参数列表的数据类型可以省略不写,因为 jvm 编译器可以通过上下文推断出数据类型,即"类型推断"
        Comparator<Integer> comparator3 = (Integer a, Integer b) -> Integer.compare(a, b);

四. 函数式接口

  • 只包含一个抽象方法的接口,称为函数式接口。
  • 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda
    表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方
    法上进行声明)。
  • 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,
    这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
    Lambda 表达式需要"函数式接口"的支持

一个抽象方法不会报错.
在这里插入图片描述
两个抽象方法编译报错.
在这里插入图片描述

五.内置四大核心函数式接口

5.1 Consumer

消费型函数接口

源码:

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);
}

Demo:
在这里插入图片描述

5.2 Supplier

供给型函数接口

源码:

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

Demo:
在这里插入图片描述

5.3 Function<T, R>

函数型函数接口

源码:

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);
}

Demo:
在这里插入图片描述

5.4 Predicate

断言型函数接口

源码:

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
}

Demo:
在这里插入图片描述

六. 其他函数式接口

学会了内置四大核心函数式接口,在学习其他的就比较简单了.具体的可以自己查看源码,看看接口中的唯一方法是什么.

部分:
在这里插入图片描述

全部:在这里插入图片描述

七. 方法引用

当要传递给 Lambda 体的操作,已经有实现的方法了,可以使用方法引用! (实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!) 方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来。 如下三种主要使用情况:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法

7.1 类::静态方法名

类为: Integer
静态方法名: compare

简单示例:
在这里插入图片描述

源码:

/** * 类::静态方法名 */
    @Test
    public void test09() {
        // 例如:创建比较器
        Comparator<Integer> comparator1 = (o1, o2) -> Integer.compare(o1, o2);
        // 等同于
        Comparator<Integer> comparator2 = Integer::compare;

        System.out.println(comparator1.compare(1, 2));
        System.out.println(comparator2.compare(1, 2));

    }

7.2 对象::实例方法名

对象: PrintStream
静态方法名: println

简单示例:
在这里插入图片描述

源码:

/** * 对象::实例方法名 */
    @Test
    public void test13() {
        // 例如:这个函数是打印传入的 name 值
        Consumer<String> consumer1 = (name) -> System.out.println(name);
        // 创建对象
        PrintStream ps = System.out;
        // 等同于
        Consumer<String> consumer2 = ps::println;

        consumer1.accept("zcsh1");
        consumer1.accept("zcsh2");

    }

7.3 类::实例方法名

类:String
实例方法名:equals

简单实例:
在这里插入图片描述

八. 构造器引用

格式:ClassName::new与函数式接口相结合,自动与函数式接口中方法兼容。 可以把构造器引用赋值给定义的方法,与构造器参数 列表要与接口中抽象方法的参数列表一致!

8.1 无参构造器引用

简单示例:
在这里插入图片描述

源码:

private class Employee {
        private String name = "zcsh";
    }


    /** * 无参构造器引用 */
    @Test
    public void test12() {
        // 例如创建一个初始的 employee 对象
        Supplier<Employee> supplier1 = () -> new Employee();
        // 等同于
        Supplier<Employee> supplier2 = Employee::new;

        System.out.println(supplier1.get().name);
        System.out.println(supplier2.get().name);

    }

8.2 无参构造器

简单示例:
在这里插入图片描述
源码:

private class Employee2 {
        private String name = "zcsh";

        public Employee2(String name) {
            this.name = name;
        }
    }

    /** * 有参构造器引用 */
    @Test
    public void test13() {
        // 例如创建一个初始的 employee 对象
        Function<String, Employee2> function1 = (name) -> new Employee2(name);
        // 等同于
        Function<String, Employee2> function2 = Employee2::new;

        System.out.println(function1.apply("zcsh1").name);
        System.out.println(function2.apply("zcsh2").name);
    }

8.3 数组引用

简单示例:
在这里插入图片描述
源码:

/** * 数组引用 */
    @Test
    public void test14() {
        // 创建一个长度为 length 的数组
        Function<Integer,Integer[]> function1 = (length) -> new Integer[length];
        // 等同于
        Function<Integer,Integer[]> function2 = Integer[]::new;

        System.out.println(function1.apply(10).length);
        System.out.println(function2.apply(10).length);

    }