24 Lambda表达式

Lambda表达式

避免你匿名内部类定义过多

可以让你的代码看起来很简洁

去掉了一堆没有意义的代码,只留下核心的逻辑

lambad表达式

按顺序一步步简化,最后用lambda

lambad表达式的本质:作为函数式接口的实例

public class TestLambda {
    //3.静态内部类
    static class Like2 implements ILike{
        @Override
        public void lambda() {
            System.out.println("i like lambda2");
        }
    }


    public static void main(String[] args) {
        //接口 实现类  相当于子类父类
        ILike like = new Like();
        like.lambda();

        like = new Like2();
        like.lambda();

        //4.局部内部类
        class Like3 implements ILike{
            @Override
            public void lambda() {
                System.out.println("i like lambda3");
            }
        }
        like = new Like3();
        like.lambda();

        //5.匿名内部类,没有类的名称,必须借助父类和接口
        like = new Like(){
            @Override
            public void lambda() {
                System.out.println("i like lambda4");
            }
        };
        like.lambda();

        //6.用lambda简化
        like = () ->{
            System.out.println("i like lambda5");
        };
        like.lambda();

    }
}

//1.定义一个函数式接口
interface ILike{
    void lambda();
}

//2.实现类
class Like implements ILike{
    @Override
    public void lambda() {
        System.out.println("i like lambda");
    }
}

总结:

​ lambda表达式只能有一行代码的情况下才能简化成为一行,如果有多行那么就用代码块包裹

​ 前提是接口为就函数式接口

​ 多个参数也可以去掉参数类型,要去掉都去掉,必须加上括号

public class TestLambda2 {


    public static void main(String[] args) {

        ILove love = null;
        //lambda表示简化
        //匿名内部类
        /*ILove love = new Love(){
           @Override
   			 public void love(int a) {
                System.out.println("i love" + "\t" +a); 
        }*/
 /*       ILove love = (int a) ->{
            System.out.println("i love" + "\t" +a);

        };
        //简化1:参数类型
        love = (a)->{
            System.out.println("i love" + "\t" +a);
    };*/
        //简化2:简化括号
        love = a -> {
            System.out.println("i love" + "\t" +a);
    };
        //简化3:去掉花括号
        love = a ->System.out.println("i love" + "\t" +a);



        love.love(2);
    }



interface ILove{
    void love(int a);
}

class Love implements ILove{
    @Override
    public void love(int a) {
        System.out.println("i love" + "\t" +a);
    }
}
}

格式:

​ ->:lambda操作符

​ 左边:lambda形参列表(其实就是接口中的抽象方法的形参列表)

​ 右边:lambda体 (其实就是重写的抽象方法的方法体)

 Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };

        int compare1 = com1.compare(12, 21);
        
        

        Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2);
        
        int compare12 = com1.compare(12, 21);

    }

总结:

​ 左边: lambda形参列表的参数列表可以省略;如果lambda形参列表只有一个参数,其一对()也可省略。

​ 右边:lambda体 应该使用一对{}包裹;如果只有一条执行语句(return 语句),可以省略{}和return关键字

方法引用

​ 方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。

方法引用的使用

  1. 使用情景:当要传递给lambda体的操作,已经有实现的方法了,可以使用方法引用。

  2. 方法引用,本质上就是lambda表达式,而lambda表达式作为函数式接口的实例。所以,方法引用,也是函数式接口的实例。

  3. 使用格式: 类(或对象):: 方法名

  4. 具体分为如下的三种情况:

    情况1 对象 :: 非静态方法

    情况2 类 :: 静态方法

    情况3 类 :: 非静态方法

  5. 方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同(针对情况1 和 情况2)

        //情况一:对象  ::  实例方法
        //Consumer中的void accept(T t)
        //PrintStream中的void print(T t)

        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("北京");

        //方法引用
        PrintStream ps = System.out;
        Consumer<String> con2 = ps::println;
        con2.accept("beijing");


//情形二: 类 :: 静态方法
        //Comparator中的int compare(T t1,T t2)
        //Integer中int compare(T t1,T t2)
        Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
        System.out.println(com1.compare(12,21));

        //方法引用
        Comparator<Integer> com2 = Integer::compare;
        System.out.println(com2.compare(12,2));


        //Function中的 R apply(T t)
        //Math 中的Long  round(Double d)
        Function<Double,Long> func1 = d -> Math.round(d);
        System.out.println(func1.apply(12.3));
        //方法引用
        Function<Double,Long> func2 = Math::round;
        System.out.println(func2.apply(12.6));


//情形三: 类 :: 实例方法(有难度)
        //Comparator中的 int compare(T t1,T t2)
        //String 中的    int t1.compareTo(t2)
        Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
        System.out.println(com1.compare("abc", "abd"));

        //方法引用
        Comparator<String> com2 = String::compareTo;
        System.out.println(com2.compare("abd","abm"));


        //BiPredicate 中的 boolean test(T t1, T t2)
        //String 中的  boolean t1.equals(t2)
        BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2);
        System.out.println(pre1.test("abc","abd"));

        BiPredicate<String,String> pre2 = String::equals;
        System.out.println(pre2.test("add","ass"));

构造器引用

和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致,抽象方法的返回值类型即为构造器所属的类的类型

		//Supplier中的 T get()
        //Person的空参构造器:Person()   T就是Person的对象,下面都这样
        Supplier<Person> sup = new Supplier<Person>() {
            @Override
            public Person get() {
                return new Person();
            }
        };

        System.out.println("==============");

        Supplier<Person> sup1 = () -> new Person();
        System.out.println(sup1.get());

        System.out.println("================");
        //构造器引用
        Supplier<Person> sup2 = Person :: new;
        System.out.println(sup2.get());
    }

//Function中的 R apply(T t)
        Function<Integer,Person> func1 = id -> new Person(id);
        Person person = func1.apply(1001);

        //构造器引用
        Function<Integer,Person> func2 = Person :: new;


        //BiFunction 中的 R apply(T t, U u)
        BiFunction<Integer,String,Person> func3 = (id, name) -> new Person(id,name);
        System.out.println(func3.apply(1001,"Tom"));

        //构造器引用
        BiFunction<Integer,String,Person> func4 = Person :: new;

数组引用

​ 可以把数组看作是一个特殊的类,则写法与构造器一致

        Function<Integer,String[]>  func = new Function<Integer, String[]>() {
            @Override
            public String[] apply(Integer integer) {
                return new String[integer];
            }
        };

        //Function中的 R apply(T t)
        Function<Integer,String[]>  func1 = length -> new String[length];

        //数组引用
        Function<Integer,String[]>  func2 = String[]::new;
        String[] strings = func2.apply(10);
        
posted @   flypiggg  阅读(65)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示