Java SE JDK8新功能--23.Lambda表达式

版权声明:转载请注明原始链接 https://blog.csdn.net/sswqzx/article/details/82975338

1、概述

简介:Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口

格式:()->{}

():接口中抽象方法的参数列表.
-> :分隔符 
{}:接口中抽象方法的实现体.

2、Lambda使用条件

使用Lambda表达式必须有接口、且接口中有且仅有一个抽象方法、

或必须有“函数式接口”作为方法的参数

函数式接口:只有一个抽象方法(Object类中的方法除外)的接口是函数式接口

3、Lambda表达式省略规则

1. 小括号内参数的类型可以省略;
2. 如果小括号内有且仅有一个参,则小括号可以省略;如果没有参数、小括号不能省
3. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。

4、Runnable接口优化

说明:Runnable接口中有且只有一个抽象方法run、所以是函数式接口、就可以使用Lambda表达式了

演示:

public class ThreadTest {
    public static void main(String[] args) {

        // 方案一 : 实现类
        // new Thread(new MyRunnable()).start();

        // 方案二 : 匿名实现类 (省略了实现类的名称)
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + " -> run ... " + i);
                }
            }
        }).start();

        // 方式三 : Lambda 表达式  (能省则省)
        // 省略1 : 接口的名称.
        // 省略2 : 抽象方法的名称.
        // 自动推导 : Thread 类的构造方法. 推导出函数式接口的名称为 Runnable, 在根据 Runnable 函数式接口就可以推导出 `抽象方法` 的名称.
        /*
        1. () : 表示抽象方法 run 的参数列表.
        2. -> : 分隔符. 参数列表 -> 方法体
        3. {} : 抽象方法的方法体实现.
         */
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + " -> run ... " + i);
            }
        }).start();

        // 主线程执行代码 ...
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " -> run ... " + i);
        }
    }
}

5、Comparator接口优化

说明:Comparator接口中有且仅有一个抽象方法compare、所以可以用Lambda表达式

需求 : 对集合中的 Student 对象进行排序. 规则为: 按照年龄从小到大排列.

演示:

public class StudentSortTest {
    public static void main(String[] args) {

        // 1. 创建一个集合, 存储多个 Student 对象
        ArrayList<Student> list = new ArrayList<>();

        list.add(new Student("张三", 18));
        list.add(new Student("李四", 16));
        list.add(new Student("王五", 19));
        list.add(new Student("赵六", 17));

        // 排序 :  函数式接口相关的方法. Collections.sort(list, Comparator函数式接口);
        // 方式一 : 实现类
        Collections.sort(list, new MyComparactor());

        // 方式二 : 匿名实现类
        Collections.sort(list, new Comparator<Student>() {

            @Override
            public int compare(Student o1, Student o2) {
                // 按照年龄从小到大
                return o1.getAge() - o2.getAge();
            }
        });

        // 方式三 : Lambda 表达式
        /*
        1. () : 抽象方法的参数列表
        2. -> : 分隔符
        3. {} : 抽象方法的实现体
         */
        Collections.sort(list, (Student o1, Student o2) -> {
            // 按照年龄从小到大
            return o1.getAge() - o2.getAge();
        });

        Collections.sort(list, (o1, o2) -> { return o1.getAge() - o2.getAge(); });
     
        Collections.sort(list, (a, b) -> a.getAge() - b.getAge());//省略后的写法

        // 遍历
        for (Student stu : list) {
            System.out.println(stu);
        }
    }
}

6、Lambda无参无返回值

package com.mvcCase.Test;

public interface Cook {
    public abstract int eat(int num1, int num2);
}
package com.mvcCase.Test;

public class LambdaTest {
    public static void main(String[] args) {

        // 调用方法, 传递 Lambda 表达式
        // 请问 : 如果一个方法是接口类型, 那么其真正需要的是该接口的实现类对象.
        // 方式一 : 匿名实现类传递参数
        keepAlive(new Cook() {
            // 方法的定义 :
            @Override
            public void eat() {
                System.out.println("吃饭、匿名实现类");
            }
        });

        // 方式二 : Lambda 表达式
        keepAlive(() -> { System.out.println("吃饭、Lambda");});

        // 方式三 : 省略原则
        keepAlive(() -> System.out.println("吃饭、Lambda简写"));
    }

    // 方法 : 必须使用 `函数式接口` 作为方法的参数类型
    public static void keepAlive(Cook cook) {

            // 接口调用抽象方法, 其真正调用的是 `实现类` 的重写方法.
            cook.eat();  // 方法的调用
        }
    }

7、Lambda有参有返回值

package com.mvcCase.Test;

public interface Cook {
    public abstract int eat(int num1, int num2);
}
package com.mvcCase.Test;

public class LambdaTest {
    public static void main(String[] args) {

        // 调用方法, 传递 Lambda 表达式
        // 请问 : 如果一个方法是接口类型, 那么其真正需要的是该接口的实现类对象.
        // 方式一 : 匿名实现类传递参数
        int sum = keepAlive(10, 10, new Cook() {
            // 方法的定义 :
            @Override
            public int eat(int num1, int num2) {
                return num1 + num2;
            }
        });

        System.out.println("总共多少次=" + sum);
        // 方式二 : Lambda 表达式
        int sum1 = keepAlive(20, 20, (n1, n2) -> { return n1 + n2; });
        System.out.println("总共多少次=" + sum1);
        // 方式三 : 省略原则
        int sum2 = keepAlive(30,30,(a1, a2)->a1+a2);
        System.out.println("总共多少次=" + sum2);
    }

    // 方法 : 必须使用 `函数式接口` 作为方法的参数类型
    public static int keepAlive(int num1, int num2, Cook cook) {

        // 接口调用抽象方法, 其真正调用的是 `实现类` 的重写方法.
        return cook.eat(num1, num2);  // 方法的调用
    }
}

猜你喜欢

转载自blog.csdn.net/sswqzx/article/details/82975338