函数式接口
概念:
针对函数式编程接口,一般可以定义为:
Consumer c = (o) -> {
System.out.println(o);
};
// 函数式编程接口都只有一个抽象方法,因此在采用这种写法时,编译器会将这段函数编译后当作该抽象方法的实现
// 如果接口有多个抽象方法,编译器就不知道这段函数应该是实现哪个方法的了。
// 因此,=后面的函数体我们就可以看成是accept函数的实现。
输入:->前面的部分,即被()包围的部分。此处只有一个输入参数,实际上输入是可以有多个的,如两个参数时写法:(a, b);当然也可以没有输入,此时直接就可以是()。
函数体:->后面的部分,即被{}包围的部分;可以是一段代码。
输出:函数式编程可以没有返回值,也可以有返回值。如果有返回值时,需要代码段的最后一句通过return的方式返回对应的值。
当函数体中只有一个语句时,可以去掉{}进一步简化:
Consumer c = (o) -> System.out.println(o);
常用的几个函数式接口:
name | type | description |
---|---|---|
Consumer | Consumer<T> | 接受T对象,不返回值 |
Predicate | Predicate<T> | 接受T对象,并返回boolean |
Function | Function<T,R> | 接受T对象,返回R对象 |
Function常用方法&&实践
Function也是一个函数式编程接口;它代表的含义是“函数”,而函数经常是有输入输出的,因此它含有一个apply方法,包含一个输入与一个输出;
除apply方法外,它还有 compose 与 andThen 及 indentity 三个方法,其使用见下述示例;
//将Function对象应用到输入的参数上,然后返回计算结果。
R apply(T t);
// 先执行调用者的apply,再执行这个after的apply
// andThen 的语义正是“一步接一步”操作,我执行完,再继续执行你
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
// 先执行这个before的apply,再执行调用者的apply
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
public static void functionTest() {
Function<Integer, Integer> f = s -> s++;
Function<Integer, Integer> g = s -> s * 2;
/**
* 下面表示在执行F时,先执行G,并且执行F时使用G的输出当作输入。
* 相当于以下代码:
* Integer a = g.apply(1);
* System.out.println(f.apply(a));
*/
System.out.println(f.compose(g).apply(1));
/**
* 表示执行F的Apply后使用其返回的值当作输入再执行G的Apply;
* 相当于以下代码
* Integer a = f.apply(1);
* System.out.println(g.apply(a));
*/
System.out.println(f.andThen(g).apply(1));
/**
* identity方法会返回一个不进行任何处理的Function,即输出与输入值相等;
*/
System.out.println(Function.identity().apply("a"));
}
说明:
compose 和 andThen 的不同之处是函数执行的顺序不同。
compose 函数先执行参数,然后执行调用者,
而 andThen 先执行调用者,然后再执行参数。
其实就是:
andThen:先执行自己的apply方法,再执行别人的apply;
compose:先执行别人的,再执行自己的apply方法;
Consumer常用方法&&实践
顾名思义,Consumer的意思就是消费,即针对某个东西我们来使用它,因此它包含有一个有输入而无输出的accept接口方法; 除accept方法,它还包含有andThen这个方法:
( 这个方法就是指定在调用当前Consumer后是否还要调用其它的Consumer )
/**
* 对给定参数执行消费操作。
* @param t 输入参数
*/
void accept(T t);
// void accept(T t) ,意为消费一个指定泛型的数据
// consumer 也有 andThen方法,跟Function中作用一样,先执行调用者的accept,再执行这个after的accept
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
举例:
public static void consumerTest() {
Consumer f = System.out::println;
Consumer f2 = n -> System.out.println(n + "-F2");
//执行完F后再执行F2的Accept方法
f.andThen(f2).accept("test");
//连续执行F的Accept方法
f.andThen(f).andThen(f).andThen(f).accept("test1");
}
Predicate常用方法&&实践
Predicate为函数式接口,predicate的中文意思是“断定”,即判断的意思,判断某个东西是否满足某种条件;
因此它包含test方法,根据输入值来做逻辑判断,其结果为True或者False。
它的使用方法示例如下:
/**
* Predicate测试
*/
private static void predicateTest() {
Predicate<String> p = o -> o.equals("test");
Predicate<String> g = o -> o.startsWith("t");
/**
* negate: 用于对原来的Predicate做取反处理;
* 如当调用p.test("test")为True时,调用p.negate().test("test")就会是False;
*/
Assert.assertFalse(p.negate().test("test"));
/**
* and: 针对同一输入值,多个Predicate均返回True时返回True,否则返回False;
*/
Assert.assertTrue(p.and(g).test("test"));
/**
* or: 针对同一输入值,多个Predicate只要有一个返回True则返回True,否则返回False
*/
Assert.assertTrue(p.or(g).test("ta"));
}