概念&语法

Lambda表达式时Java 8中提供的一个重要的新特性,它支持Java进行简单的“函数式编程”

通过函数式接口 + Lambda表达式,可以写出更简洁、更灵活的代码

Lambda表达式写法(特殊情况下,还会有些变体):

  • (参数列表) -> {多条语句}
  • (参数列表) -> 单条语句
  • (参数列表) -> 表达式

举例如下:

// 无参,无返回值,单语句
() -> System.out.println("test")

// 有一个参数,无返回值,单语句
(x) -> System.out.println(x)
// >> 省了了小括号
x -> System.out.println(x)

// 有多个参数,且有返回值,单语句
(x,y) -> Interger.compare(x,y)

// 有多个参数,且有返回值,多语句
(x,y) -> {
	System.out.println("test");
  return Interger.compare(x,y);
}


函数式接口:一个只有一个抽象方法(不包括object中已经定义的方法)的接口

举例说明

// 函数式接口
interface MyRunnable {
	void run();
}

// 不是函数式接口。原因:方法有默认实现,不是抽象方法
interface MyRunnable {
	default void run() {
  	System.out.println("run");
  }
}

// 函数式接口
interface MyRunnable {
	void run();
  // 该方法已在Object中定义了
  String toString();
}


基本使用步骤

// 1. 定义函数式接口
interface MyRunnable {
	void run();
}

// 2. 使用函数式接口
void test(MyRunnable mr){
	...
  mr.run();
	...
}

// 3. 根据需要,传入不同的lamda表达式
test(()->System.out.println("xxx"));
test(()->{
	System.out.println("xxx");
	System.out.println("yyy");
});

注意:定义函数式接口时,可以添加@FunctionalInterface注解(作用:编译器会强制检查该接口是否是函数式接口)


内置的函数式接口

为了更方便Lambda表达式的使用,Java内置了一些函数式接口。基本都在rt.jar的java.util.function包下。常用的函数式接口如下:

Function<T,R>

package java.util.function;

import java.util.Objects;

/**
 * 表示接收一个参数并返回一个结果的函数
 * 
 * 函数方法是R apply(T t)
 * @since 1.8
 */
@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    /**
     * 组合Function,将另一个Function(before)的apply结果作为当前Function的apply参数
     * 即先执行before的apply,并将其结果作为当前Function的apply的参数执行
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * 组合Function,将当前Function的apply结果作为另一个Function(after)的apply参数
     * 即先执行当前Function的apply,并将其结果作为after的apply的参数执行
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * 总是将参数作为结果返回的Function
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Predicate<T>

package java.util.function;

import java.util.Objects;

/**
 * 表达对一个参数(T)的断言
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> {

    /**
     * 对参数进行断言,符合断言,则返回true;否则返回false
     *
     */
    boolean test(T t);

    /**
     * 增加断言,且同时满足时,才返回true
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    /**
     * 断言结果取反
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    /**
     * 增加断言,只要满足一个断言,就返回true
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * 判断两个对象是否相等的断言
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

Consumer<T>

package java.util.function;

import java.util.Objects;

/**
* 表达一个操作:接收一个参数,且没有返回值
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    /**
     * 组合Consumer,在执行完当前Consumer的accept(T),接着执行after的accept(T)
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}


Supplier<T>

package java.util.function;

/**
 * 表达生成一个结果
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

    T get();
}


方法引用

如果Lambda表达式->右边要执行的表达式只是调用一个类已有的方法,那么可以使用“方法引用”来代替Lambda表达式

// ****只有一个参数,调用参数的无参方法(写法:对象::实例方法名)****
Consumer<String> sc = (x)-> System.out.println(x);
// 等效
Consumer<String> sc = System.out::println; 

// ****只有一个参数,参数作为类静态方法的参数(写法:类名::静态方法名)****
Function<Integer,String> sf = (x) -> String.valueOf(x);
// 等效
Function<Integer,String> sf = String::valueOf;

// ****有多个参数,第一个参数当作方法的调用者,其他参数作为方法的参数(写法:类名::实例方法名)****
BiPredicate<String,String> sbp = (x,y) -> x.equals(y);
// 等效
BiPredicate<String,String> sbp = String::equals;

// **** 调用无参的构造方法(写法:类名::new)
Supplier<User> us = () -> new User();
// 等效
Supplier<User> us = User:new;

尝试解释lambda表达式的写法演进

interface MyInterface {
	String func(int i);
}

// lambda表达式的写法演进

// >> 写法1
MyInterface mi = new MyInterface() {
	@Override
  public String func(int i) {
  	return String.valueOf(i);
  }
};

// >> 写法2
MyInterface mi = (i) -> {
	return String.valueOf(i);
};

// >> 写法3
MyInterface mi = (i) -> String.valueOf(i); 

// >> 写法4
MyInterface mi = String::valueOf;