Java24lambda表达式:函数式编程

Posted 码农编程录

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java24lambda表达式:函数式编程相关的知识,希望对你有一定的参考价值。


1.lambda表达式标准语法:()->{}

package com.itheima01.boot;
/*
*   函数式编程 语法 (JDK8): 函数(公式)  ->  java方法
*       作用: 简化代码编写
*       1. lambda表达式
*           1. 标准语法
*           2. 简略语法
*       2. 运用: Stream流
*/
public class BootDemo {
    public static void main(String[] args) {
        //匿名内部类
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();

        
        //lambda表达式
        new Thread(
                () -> {
                    System.out.println(Thread.currentThread().getName());
                }
        ).start();
    }
}
package com.itheima02.lambda;
/*
    lambda表达式 -> 函数式编程(不在乎什么对象, 在乎是什么方法)
        方法重要三部分
        1. 参数列表
        2. 方法体
        3. 返回值

*   标准语法
*       (参数列表)
*       -> : lambda符号,连接作用
*       { 方法体,返回值 }
*/
public class StandardDemo {
    public static void main(String[] args) {
        Cooker cooker = new Cooker() { //匿名内部类 ,和method()无关
            @Override
            public void cook() {
                System.out.println("猪肉炖粉条");
            }
        };
        method(cooker);

//11111111111111111111111111111111111111111111111111111111111111111	
        Cooker cooker2 =  () -> {
            System.out.println("小鸡炖蘑菇");
        };
        method(cooker2);
    }    
    private static void method(Cooker cooker) { //参数类型是接口 -> 多态。调用此方法必须传入此接口的实现类对象。
        // System.out.println(1); //1 先于 猪肉炖粉条 打印
        cooker.cook(); //父类调用方法执行子类重写方法
    }
}
interface Cooker{  
    void cook(); //这方法无参无返回
}
package com.itheima02.lambda;
/*
*  lambda表达式:在乎的方法: 拿什么参数去做什么事情,返回什么结果
*         (参数列表) -> { return xx; }
*/
public class StandardDemo02 {
    public static void main(String[] args) {
        Calculator c1 = new Calculator() {
            @Override
            public int calc(int c, int d) {
                return c + d;
            }
        };
        method(c1);
        
//1111111111111111111111111111111111111111111111111111111111111111
        Calculator c2 = (int o1,int o2) -> {
            return o1 - o2;
        };
        method(c2);
    }

//1111111111111111111111111111111111111111111111111111111111111111
    private static void method(Calculator calculator) {
        int result = calculator.calc(1, 2); //父类调用方法执行子类重写方法
        System.out.println(result);
    }
}
interface Calculator{    
    int calc(int a, int b); //有参有返回
}
package com.itheima03.prefix;
/*
*   lambda表达式的使用前提
*       1. 接口 : 有且仅有一个抽象方法 (需要被重写) 的接口
*       2. 上下文推导
*   lambda表达式可以看成 极为简化的 匿名内部类对象
*       接口的实现 (函数: 方法)
*/
public class PrefixDemo {
    public static void main(String[] args) {
        Cooker c1 = new Cooker() {
            @Override
            public void cooker() {
                System.out.println("翠花上酸菜");
            }
        };
        method(c1);

//11111111111111111111111111111111111111111111111111111111111111111	
        /*
        *   匿名内部类对比
        *   lambda表达式 : 1. 省略了new + 接口名 (因为上下文推导)
        *        2. 省略了方法名 (因为接口只有一个抽象方法,所以方法名不重要)
        */
        //上文(Cooker c2 = 是上文 ,() ->...是下文)推导
        Cooker c2 = () -> {
            System.out.println("蚂蚁上树");
        };
        method(c2);
        
//111111111111111111111111111111111111111111111111111111111111111111		
        //下文推导。上下文有其一即可
        method( () -> {
            System.out.println("蚂蚁上树");
        });
    }
    private static void method(Cooker cooker) {
        cooker.cooker();
    }
}
interface Cooker{
    void cooker(); //有且仅有一个抽象方法
}
package com.itheima03.prefix;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/*
*   lambda表达式的运用:1. Runnable接口
*       		       2. Comparator接口
*/
public class UseDemo {
    public static void main(String[] args) {
//        method01();
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,5,3,2,4,1);
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        System.out.println(list); //[1,2,3,4,5]
        
        Collections.sort(list,(Integer o1,Integer o2) -> {
            return o2 - o1;
        });
        System.out.println(list); //[5,4,3,2,1]
    }

//11111111111111111111111111111111111111111111111111111111111111111111111111
    private static void method01() {  
        new Thread(new Runnable() {
            @Override
            public void run() { 
                System.out.println(Thread.currentThread().getName() + ": 嘻嘻"); //Thread-0:嘻嘻
            }
        }).start();
        
//1111111111111111111111111111111111111111111111111111111111111111111111111
        Runnable runnable = () -> {
            System.out.println(Thread.currentThread().getName() + ":哈哈"); //Thread-1:哈哈
        };
        new Thread(runnable).start();
        
//1111111111111111111111111111111111111111111111111111111111111111111111111
        new Thread(()->{
            System.out.println(Thread.currentThread().getName() + ":呵呵"); //Thread-2:呵呵
        }).start();
    }
}

2.lambda表达式简略语法:可推导即可省略

package com.itheima04.simple;
/*
*       1. 参数类型可以省略 (接口抽象方法只有一个,参数列表只有一个,什么类型不需要特地声明)
*       2. 如果方法体中只有一行代码,那么 {}和return和; 都可以省略
*       3. 如果参数列表 有且只有一个参数,那么()可以省略
*/
public class SimpleDemo {
    public static void main(String[] args) {
        //lambda编写: 拿什么东西去做什么事,结果?
        method((int a,int b)-> { return a + b;});

        method((a,b) -> {return a+b;}); //可以

        method((a,b) -> a+b); //可以,如上的省略

        method((a,b) -> { 
            int sum = a+b;
            return sum; //两句不能去掉{}..return..
        });		
        
//1111111111111111111111111111111111111111111111111111111111111111111111111111
        method02((String cai) -> {
            System.out.println("开水煮" + cai); //子类重写的方法 //开水煮大白菜
        });

        method02((cai) -> System.out.println("醋溜" + cai));

        method02(cai -> System.out.println("韩式泡" + cai)); //空参必须写()
    }
    
//1111111111111111111111111111111111111111111111111111111111111111111111111111
    private static void method02(Cooker cooker) {
        cooker.cook("大白菜"); //无返回值,父类调用方法执行子类重写的方法,此时cai="大白菜"。这行是主体。
    }
    private static void method(Calculator calculator) {
        int result = calculator.calc(1, 2);
        System.out.println(result);
    }
}
interface Calculator{
    int calc(int a,int b);
}
interface Cooker{
    void cook(String cai);
}
package com.itheima04.simple;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/*
*   lambda表达式简略语法运用
*       1. Runnbale接口
*       2. Comparator
*/
public class UseDemo {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("嘻嘻");
            }
        }).start();
        
        new Thread(() -> System.out.println("呵呵")).start();	
        	
//11111111111111111111111111111111111111111111111111111111111111111
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,5,3,4,2,1);
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        System.out.println(list);
        
        Collections.sort(list,(o1,o2) -> o2 -o1);
        System.out.println(list);
    }
}

3.lambda表达式原理:lambda效率比匿名内部类高

package com.itheima05.theory;
import java.util.ArrayList;
import java.util.List;
/*
*   lambda表达式和匿名内部类
*       0.lambda表达式 可以算是 一种 匿名内部类的 简化语法
*       1.lambda表达式能不能完全替代匿名内部类?不能
*           1.lambda表达式只能用在(有且仅有一个抽象方法需要被重写的)接口
*           2.匿名内部类(接口比较多,类实际上也可以)
*
*       2.lambda表达式是不是匿名内部类的语法糖(原理完全相同,语法更为简练称为语法糖)
*           不是
*           1.匿名内部类 是 类
*           2.lambda表达式不是 类,是可以替代对象的函数
*/
public class LambdaDemo {     // LambdaDemo.class
    public static void main(String[] args) {        
        Runnable runnable = new Runnable() { // LambdaDemo$1.class(编译生成) ,所以匿名内部类是类。idea中run集成了编译和运行
            @Override
            public void run() {
                System.out.println("嘻嘻");
            }
        };
  
//11111111111111111111111111111111111111111111111111111111111111111111111
        Runnable runnable2 = new Runnable() { // LambdaDemo$2.class 
            @Override
            public void run() {
                System.out.println("嘻嘻2");
            }
        };
    //接口类型 引用 = 接口实现类对象(看成,但实际上不是) //没有.class文件生成
        Runnable runnable3 = () -> System.out.println("呼呼");
    }
}

4.两个函数式接口:Consumer ,Predicate

package com.itheima06.function;
import java.util.Comparator;
/*
*   函数式接口:
*       1. 定义 : 有且仅有一个抽象方法(需要被重写)的接口
*       2. 作用 : 支持函数式编程(A.lambda表达式 B.方法引用)
*       3. 已学习 : Runnbale , Comparator两个函数式接口
*       4. 注解: @FunctionalInterface
*               写在接口声明上, 检查此接口是否是函数式接口,如果不是编译报错
*/
public class FunctionDemo {
    public static void main(String[] args) {
//        Runnable
    }
}
@FunctionalInterface
interface A{
    void eat(); //需要重写的抽象方法,只一个
    String toString(); // 不需要重写的抽象方法
    static void method01(){ //不影响@FunctionalInterface,静态方法一定不能被重写
    }
    default void method02(){
    }
}

//1111111111111111111111111111111111111111111111111111111111111
interface B{
    String toString();  
}
//Object和接口B中拥有相同方法,C先继承Object的方法,当成接口B的重写
class C implements B{ //class C extends Object implements B   //class C 都可以
    @Override
    public String toString() { //重写也可以
        return super.toString();
    }
}
package com.itheima06.function;
import java.util.function.Consumer;
/*
* JDK8 : java.util.function包提供了很多函数式接口 -> 函数式编程(Stream流)
*   1. Consumer : 消费者
*           public interface Consumer<T> {             
*               void accept(T t); //有参无返回
*           }
*   2. Predicate
*/
public class FunctionDemo02 {
    public static void main(String[] args) {
        method(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("水煮" + s);
            }
        });
        
        method(s -> System.out.println("清蒸" + s));
    }

//1111111111111111111111111111111111111111111111111111111111111    
    private static void method(Consumer<String> consumer) {
        consumer.accept("大白菜");
    }
}

在这里插入图片描述

package com.itheima06.function;
import java.util.function.Predicate;
/*
* 2. Predicate : 推断
*       public interface Predicate<T> {       
*           boolean test(T t); //有参有boolean返回值
*       }
*/
public class FunctionDemo03 {
    public static void main(String[] args) {        
        method(new Predicate<String>() { //判断参数字符串 长度 是否超过5
            @Override
            public boolean test(String s) {
//                if(s.length() > 5){
//                    return true;
//                }
//                return false;
                return s.length() > 5; //可以。且只有一句
            }
        });

        method(s->s.length() > 5);
    }

以上是关于Java24lambda表达式:函数式编程的主要内容,如果未能解决你的问题,请参考以下文章

Java函数式编程和lambda表达式

Java函数式编程和lambda表达式

Java开发『函数式编程』——Lambda表达式

《On Java 8》中文版 第十三章 函数式编程

Java 函数式编程和Lambda表达式

Java8函数式编程