• Java中级——lambda表达式


    lambda表达式是什么?

    lambda表达式是一个可传递的代码块,可以在以后执行一次或多次

    lambda实现

    Java自带的数组排序方法sort需要传递一个泛型数组和继承了该泛型的Comparator实现类

    Arrays.sort(T[] a, Comparator c)
    
    • 1

    要使用它排序数组,需要创建自定义Comparator,重新其中的compare方法

    class Person {
        private String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    
    class MyComparator implements Comparator {
    
        @Override
        public int compare(Person o1, Person o2) {
            return o1.getName().length() - o2.getName().length();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    调用过程

    Person[] people = {new Person("tom"), new Person("john")};
    Arrays.sort(people, new MyComparator());
    
    • 1
    • 2

    在上述调用过程,不用在意哪个类实现了Comparator接口及重写compare方法,真正该在意的是两个参数(Person o1, Person o2) 及对它们的操作

    因为在java中不能直接传递代码块,所有代码都必须放在类中的方法体,所以我们真正在意的是这个部分的代码块

    (Person o1, Person o2) {
            return o1.getName().length() - o2.getName().length();
        }
    
    • 1
    • 2
    • 3

    使用Lambda表达式可以让我们跳过类和方法,直接传递代码块,需加上->

    Arrays.sort(people, (Person o1, Person o2) -> {
        return o1.getName().length() - o2.getName().length();
    });
    
    • 1
    • 2
    • 3

    可以更加简洁,Lambda表达式可以自动推断出参数类型和返回类型,当代码只有一行时还可省略{}

    Arrays.sort(people, (o1, o2) -> o1.getName().length() - o2.getName().length());
    
    • 1
    • 当参数只有一个时,还可省略()
    • 但没有参数时,仍需()

    函数式接口

    只有一个抽象方法的接口称为函数式接口,当使用该接口的对象时,就可用Lambda表达式替换,即Lambda表达式可以传递到接口,如创建Comparator接口:

    Comparator myComparator = (o1, o2) -> o1.getName().length() - o2.getName().length();
    Arrays.sort(people, myComparator);
    
    • 1
    • 2

    又如BiFunction描述了参数类型为T、U,返回类型为R的函数

    BiFunction biFunction=(s1, s2) -> s1.length() - s2.length();
    
    • 1

    方法引用(没明白)

    Java有现成的方法可以完成你想要传递到其他代码的某个动作,主要有3种情况:

    • object::instanceMethod 对应System.out::println等价于x->System.out.println(x)
    • Class::staticMethod 对应Math::pow等价于(x,y)->Math.pow(x,y)
    • Class::instanceMethod 对应String::compareToIgnoreCase等价于(x,y)->x.compareToIgnoreCase(y)

    列如对字符串数组排序

    String[] s = {"tom", "john"};
    Arrays.sort(s, String::compareToIgnoreCase);
    
    • 1
    • 2

    String::compareToIgnoreCase相当于以下两种情况

    Arrays.sort(s, new Comparator() {
        @Override
        public int compare(String o1, String o2) {
            return o1.compareToIgnoreCase(o2);
        }
    });
    
    Arrays.sort(s, (o1, o2) -> o1.compareToIgnoreCase(o2));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    凡是使用函数式接口的地方即可使用方法引用

    interface NormalInterface {
        void print(String s);
    }
    void printTest(NormalInterface normalInterface) {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    传入System.out::println为打印后换行,传入System.out::print为打印不换行

    printTest(System.out::println);
    printTest(System.out::print);
    
    printTest(new NormalInterface() {
        @Override
        public void print(String s) {
            System.out.println(s);
        }
    });
    printTest(s1-> System.out.println(s1));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    构造器引用

    class Person {
        private String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Person::new会推导出并选择带有String参数的构造器

    ArrayList names = new ArrayList<>();
    names.add("tom");
    names.add("john");
    Stream stream = names.stream().map(Person::new);
    List people = stream.collect(Collectors.toList());
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Java无法构造泛型类型T的数组,使用数组构造器引用可以克服这个问题,stream.toArray()默认返回是一个Object类型数组

    Object[] objects = stream.toArray();
    
    • 1

    通过数组构造器引用可让其返回正确的类型

    Person[] people = stream.toArray(Person[]::new);
    
    • 1

    变量作用域

    Lambda表达式中使用的变量必须是不能改变的,即初始化之后就不会再赋新值

  • 相关阅读:
    爬虫常用笔记总结
    110. 平衡二叉树
    【接口测试】工具篇Postman
    数据仓库
    内存取证系列1
    《实现领域驱动设计》-聚合
    猿创征文|手把手教你微服务分布式事务与Seata框架源码分析
    想设计一个高并发的消息中间件前,先熟悉一下这些知识点
    MySql 数据库【表】
    python扫描微信QQ二维码
  • 原文地址:https://blog.csdn.net/qq_35258036/article/details/120066252