Java 高级 Lambda表达式函数式编程思想(函数式接口)

    技术2022-07-11  84

    1、 函数式编程思想

    开篇废话: 在数学中,函数就是有输入量、输出量的一套计算方案,也就是“那什么东西做什么事情” 面向对象过分强调“必须通过对象的形式来做事情” 函数式思想则尽量忽略面向对象的复杂语法–强调做什么,而不是以什么形式做

    方式思想面向对象做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情函数式编程思想只要能获取到结果,谁去做,怎么做都不重要,忠实的是结果,不重视过程

    2、Lambda 前生今世

    我们从北京到上海,可以选择如上图任意种方式。 但是我们真正的目的是到达上海,而如何才能到达上海的形式并不重要,所以我们一直在探索有没有比高铁更好地方式:飞机

    而现在这种飞机(甚至是飞船)已经诞生:2014年3月Oracle 所发布的Java 8(JDK1.8)中,加入了Lambda表达式的重量级新特性,为我们打开了新世界的大门

    3、从多线程->匿名内部类->引入Lambda

    从线程的实现方式中,我们采用了匿名内部类,但是仍存在代码的冗余,此时需要引入Lambda(只为了目的,不考虑过程)

    ↓ Runnable接口实现类代码:

    public class RunnableImpl implements Runnable { public void run() { System.out.println("执行线程体"); } }

    ↓ 主线程代码:

    public class ThreadLambda { public static void main(String[] args) { RunnableImpl runnable = new RunnableImpl(); Thread thread = new Thread(runnable); thread.start(); // ========================= 优化 ========================= // 匿名内部类写法 Runnable r = new Runnable() { public void run() { System.out.println("第一次优化"); } }; new Thread(r).start(); // ========================= 优化 ========================= // 匿名内部类写法 new Thread(new Runnable() { public void run() { System.out.println("第二次优化"); } }).start(); } }

    Lambda 更优写法

    ↓ 从匿名内部类,去掉冗余优化成Lambda表达式:

    public class ThreadLambda2 { public static void main(String[] args) { // ========================= 优化 ========================= new Thread(new Runnable() { public void run() { System.out.println("第二次优化"); } }).start(); // 使用Lambda 表达式,实现多线程 new Thread(() -> { System.out.println("kkk"); }).start(); } }

    4、 Lambda 标准格式

    Lambda省去面向对象的条条框框,格式由3部分组成

    一些参数一个箭头一段代码

    Lambda表达式的标准格式为:

    (参数类型 参数名称)-> { 代码语句}

    格式说明:

    小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则使用逗号分隔->是新引入的语法格式,代表指向动作大括号内的语法与传统方法体要求基本一致

    5、 Lambda 标准格式(无参数无返回)实例

    ↓ 代码实现:

    public class InvokeCook { public static void main(String[] args) { // 嗲用invokeCook 方法,参数是Cook接口,传递Cook接口的匿名内部类对象 invokeCook(new Cook(){ @Override public void makeFood() { System.out.println("吃饭啦"); } }); // 使用Lambda 标准格式 调用 invokeCook方法 invokeCook(()->{ System.out.println("吃饭啦(Lambda)"); }); } private static void invokeCook(Cook cook){ cook.makeFood(); } }

    5、 Lambda 的参数和返回值 实例

    需求: 使用数组存储过个Person对象 对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序

    ↓ 实体类 Person 代码如下:

    public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }

    ↓ main 主线程 代码如下:

    public class ArraysLambda { public static void main(String[] args) { // 使用数组存储过个Person对象 Person[] arr = { new Person("CTRA", 2), new Person("lily", 3), new Person("katy", 6), }; // 对数组中的Person对象使用Arrays的sort方法通过年龄进行升序(前边-后边)排序 // Arrays.sort(arr, new Comparator<Person>() { // @Override // public int compare(Person o1, Person o2) { // return o1.getAge()-o2.getAge(); // } // }); // 使用lambda表达式,简化匿名内部类 Arrays.sort(arr,(Person o1, Person o2)->{ return o1.getAge()-o2.getAge(); }); for (Person person : arr) { System.out.println(person); } } }

    7、 Lambda 标准格式(有参数有返回)实例

    需求: 给定一个计算器Caculator接口,内含抽象方法calc可以将俩个int数字相加得到和值 使用Lambda的标准格式调用invokeCalc 方法,完成120和130相加计算

    ↓ 计算器Caculator接口,代码实现:

    public interface Caculator { int Caculator(int a ,int b); }

    ↓ main主线程方法,分别使用:匿名内部类、Lambda表达式的方式来实现需求:

    public class CaculLambda { public static void main(String[] args) { // 首先使用 匿名内部类 invokeCalc(140,120,new Caculator(){ @Override public int Caculator(int a, int b) { return a+b; } }); // 使用Lambda表达式 invokeCalc(140,120,(int a, int b)->{ return a+b; }); } // 使用Lambda的标准格式调用invokeCalc public static void invokeCalc(int a, int b,Caculator c) { int sum = c.Caculator(a,b); System.out.println("相加的值:"+sum ); } }

    8、Lambda 省略格式

    可推导可省略

    Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都是可以忽略的。 如上Lambda代码可以省略的写法: ↓ 原代码:

    // 使用Lambda表达式 invokeCalc(140,120,(int a, int b)->{ return a+b; });

    ↓ 再次省略的代码:

    invokeCalc(140, 120, (a, b) -> a + b);

    省略规则

    在Lambda标准格式的基础上,使用省略写法的规则为:

    小括号内参数的类型可以省略如果小括号内有且仅有一个参数,小括号可以省略如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号,return关键字及语句分号

    9、Lambda 的使用前提

    使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。 无论是JDK内置的Runnable、comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda使用Lambda必须具有上下文推断 也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例有且仅有一个抽象方法的接口,成为“函数式接口”
    Processed: 0.009, SQL: 9