Java 8 新特性之 lambda 表达式以及 函数式编程

351 阅读4分钟

lambda表达式是Java 8的一个很重要的新特性,对于我们Java开发者来说,学会使用lambda是十分重要滴。

本文带你快速学会并掌握lambda表达式的使用以及函数式编程~~~

Quick Start

lambda表达式能用在两个地方:

  1. 创建匿名内部类
  2. 创建对象

我们直接上代码

==创建匿名内部类==

public static void main(String[] args) {
    // 使用 lambda 表达式创建匿名内部类
    Thread thread = new Thread(() -> {
        System.out.println("Run!");
    });
    // 以下为优化
    // 由于只有一行代码,可以对 lambda 表达式进行优化
    Thread thread = new Thread(() -> System.out.println("Run!");
}

==创建对象==

public static void main(String[] args) {
    // 这里我直接使用了 Integer 对象,大家完全可以换成自己创建的对象
    Comparator<Integer> comparator = (Integer n1, Integer n2) -> {return n1 - n2;};
    // Apple 这个实体有 name(String)、weight(int) 这个两个属性
    Comparator<Apple> comparatorApple = (Apple a1, Apple a2) -> {return a1.getWeight() - a2.getWeight();};
    
    // 实际上,可以利用类型推导进行优化
    Comparator<Integer> comparator = (n1, n2) -> {return n1 - n2;};
    Comparator<Apple> comparatorApple = (a1, a2) -> {return a1.getWeight() - a2.getWeight();};
    
    // 更进一步,由于只有一行
    Comparator<Integer> comparator = (n1, n2) -> n1 - n2;
    Comparator<Apple> comparatorApple = (a1, a2) -> a1.getWeight() - a2.getWeight();
    
    // 由于 Integer 本身自带比较方法,我们可以使用方法引用再次优化
    Comparator<Integer> comparator = Integer::compareTo;
}

怎么样,lambda表达式漂亮吧!

相信大家也看到了我对代码的优化,这些就涉及到了lambda表达式更进一步的学习,引用

引用

方法引用

我们能使用的有方法引用以及构造函数引用,上面的代码已经演示过方法引用,这是个什么东西呢,

Comparator<Integer> comparator = Integer::compareTo;

给大家看看如果不使用方法引用的代码是怎么样的,

Comparator<Integer> comparator = (n1, n2) -> n1.compareTo(n2);

可以看到,它会默认根据我们的输入的参数自动将变量代入,这个时候有人就会问了,使用了方法引用的比较器,比较出来的结果是升序还是降序啊。这里都给你安排好了。

Comparator<Integer> comparator = Integer::compareTo;
List<Integer> list = Arrays.asList(5,4,3,2,1);
list.sort(comparator);
System.out.println(list);
// 结果 [1, 2, 3, 4, 5]

可以看到,默认是升序的。

构造函数引用

能理解方法引用的话,构造函数的引用就比较好理解了,其实就是在创建对象的时候,这个对象是一个函数式接口,就可以使用构造函数引用,我们继续看代码。

这里会使用到Java自带的一个函数式接口Supplier

// 原来
Supplier<Apple> supplier = new Supplier<Apple>() {
    @Override
    public Apple get() {
        return new Apple();
    }
};

// 构造函数引用
Supplier<Apple> supplier = Apple::new;

通过对比,相比大家也看到了lambda表达式结合引用的优美表达,简化代码的同时又增强了代码的可读性。

配合函数式接口

随着lambda特性一起来的其实还有很多函数式接口,大家如果想将lambda玩的更加流畅的话,建议了解一下:

  • Predicate ----> 提供了 test 方法,用来判断是否符合要求
  • Consumer ----> 提供了 accept 方法,用来接收对象并进行消费
  • Supplier -----> 提供了 get 方法,用来生产
  • Function -----> 提供了 apply 方法,有返回有参数,可自行diy
// Predicate  ----> 提供了 test 方法,用来判断是否符合要求
private static void predicate() {
    Predicate<String> predicate = (s) -> s.length() > 5;
    System.out.println(predicate.test("holdonbei"));
}

// Consumer ----> 提供了 accept 方法,用来接收对象并进行消费
private static void consumer() {
    Consumer<String> c1 = System.out::println;
    c1.accept("Holdonbei");
}

// Supplier    -----> 提供了 get 方法,用来生产
private static void supplier() {
    Supplier<String> supplier = () -> "holdonbei";
    System.out.println(supplier.get());
}

// Function    -----> 提供了 apply 方法,有返回有参数,可自行`diy`
private static void function() {
    Function<String, Integer> f = String::length;
}

除了这四个接口之外,JDK还额外提供了其他接口,有兴趣的小伙伴可以自行了解哈~

类型推导

类型推导这块其实前面已经通过代码演示过了,在函数式接口中,我们的入参是可以提前确定的,比如:

Comparator<Integer> comparator = (n1, n2) -> n1 - n2;

由于前面已经在尖括号中给出了Integer的说明,所以lambda表达式中我们可以不再注明类型,Java会自动给我们进行类型推导。

今天就到这里~

求知若饥,虚心若愚。这里是太一coding,我们下次再见~