Java中级——lambda表达式

lambda表达式

  • lambda表达式是什么?
  • lambda实现
  • 函数式接口
  • 方法引用(没明白)
  • 构造器引用
  • 变量作用域

lambda表达式是什么?

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

lambda实现

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

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

要使用它排序数组,需要创建自定义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();
    }
}

调用过程

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

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

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

(Person o1, Person o2) {
        return o1.getName().length() - o2.getName().length();
    }

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

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

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

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

函数式接口

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

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

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

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

方法引用(没明白)

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);

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));

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

interface NormalInterface {
    void print(String s);
}
void printTest(NormalInterface normalInterface) {

}

传入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));

构造器引用

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

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());

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

Object[] objects = stream.toArray();

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

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

变量作用域

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

你可能感兴趣的:(#,Java中级,java,python,开发语言)