函数式接口
内置常用的函数式接口位于java.util.function.*包中。
常用函数式接口Function、consumer、predicate、supplier等。
Lambda表达式 && FunctionalInterface
接口由@FunctionalInterface注解标注,该注解仅仅为定义约束,不注解也不会影响功能(从code规范上应该要注解),只要满足函数式接口定义都属于函数式接口(接口有且只能有个一个抽象方法)。
函数式接口为普通接口增加了更严格的约定;
lambda表达式是匿名类的简化书写形式,但lambda只能用于函数式接口;
即lambda表达式只能基于函数式接口而存在,因此是类接口实例化的简化书写形式,更简洁、方便和灵活。
@FunctionalInterface
public interface PrintFunction<T> {
void print(T t);
}
上面定义了一个函数式接口,有且只有一个抽象方法。接口使用泛型T,便于实现不同类型的参数打印。
PrintFunction<String> pf = new PrintFunction<String>() {
@Override
public void print(String s) {
System.out.println(s);
}
};
pf.print("a"); //a
上面通过匿名类方式直接实现了接口并实例化,并使用方法打印“a”。
PrintFunction<String> pf = (s) -> {
System.out.println(s);
};
pf.print("b");
上面通过lambda方式实现了接口并实例化,并调用方法print打印“b”,(s) 为入参,大括号内是方法的实现。大括号结束有分号。由于只有一个语句,可以省略{},只有一个参数,可以省略()。即:s -> System.out.println(s) 。
对比看lambda也就是书写形式上简化了。也因为lambda的这种书写形式,所以要求接口有且仅有一个抽象方法,便于直接用 “->” 实现。
这个lambda表达式是基于PrintFunction接口的定义来写的,编译器会按照接口定义检查表达式书写是否正确。
PrintFunction<String> pf = System.out::println;
pf.print("b"); //b
上面代码是对lambda表达式更简化的书写,System.out是指定的类,println是指定的方法,该方法只有一个入参,正好接口方法只会传入一个入参,因此可以正好匹配。所以只需要写明具体类的具体方法即可,编译器会自动识别及解析出来。
lambda表达式一定是基于某个接口定义而书写的,其他书写格式可参考lambda语法。
Function
接收T对象,返回R对象。
先看源码(去掉了注释)
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
Function接口包含两个default方法及一个static方法。
default方法compose:先执行before入参的函数,再执行自身函数;
default方法andThen:先执行自身函数,再执行after入参的函数。
Function<Integer, Integer> f = s -> s++;
Function<Integer, Integer> g = s -> s * 2;
/**
* f.apply( g.apply(1) )
*/
System.out.println(f.compose(g).apply(1)); // 2
使用该函数式接口时,先定义函数体,再调用该函数体方法执行(与匿名类只是书写形式不一样),lambda简洁的形式,让程序逻辑更灵活。
如上代码,f.compose(g),将g函数作为入参,与当前函数的方法一起构成了复杂的方法,该复杂的方法: