赞
踩
JDK8的1个新特性就是支持函数式接口(Functional Interface)。
函数式接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为Lambda表达式。
我们也可以自行定义函数式接口,如:
@FunctionalInterface
interface GreetingService{
void sayMessage(String message);
}
然后通过Lambda表达式来定义接口实现(JAVA8之前一般使用匿名类来实现):
public class GreetingServiceTest {
public static void main(String[] args) {
GreetingService greetingService = message -> {
System.out.println("Hello " + message);
};
greetingService.sayMessage("Mary");
}
}
执行返回:
Hello Mary
JDK8官方也为我们定义了一些常用的函数式接口,如下图所示:
接下来,我重点介绍其中比较重要的几个函数式接口。
接收1个输入参数,返回1个结果。
@FunctionalInterface
public interface Function<T, R> {
// 将T类型转化为R类型
R apply(T t);
// 先执行参数传入的Function,再执行本Function
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
// 和compose相反,先执行本Function,再执行参数传入的Function
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
// 静态方法,返回传入的泛型T自身
static <T> Function<T, T> identity() {
return t -> t;
}
}
public class FunctionTest {
public static Integer calculate(Integer i, Function<Integer, Integer> function){
return function.apply(i);
}
public static void main(String[] args) {
Function<Integer, Integer> func1 = i -> {return i+5;};
Function<Integer, Integer> func2 = i -> {return i*5;};
System.out.println(calculate(6, func1));
System.out.println(calculate(6, func2));
System.out.println(calculate(6, func1.compose(func2)));
System.out.println(calculate(6, func1.andThen(func2)));
System.out.println(Function.identity().apply("6+5"));
}
}
执行输出:
11
30
35
55
6+5
生产函数,无参数,返回1个结果。
@FunctionalInterface
public interface Supplier<T> {
// 生产1个元素
T get();
}
public class SupplierTest {
public static void main(String[] args) {
Supplier<String> supplier = () -> {return "商品";};
System.out.println(supplier.get());
}
}
执行输出:
商品
消费函数,接收1个输入参数并且无返回的操作。
@FunctionalInterface
public interface Consumer<T> {
// 消费输入t
void accept(T t);
// 先执行本接口的消费逻辑,再执行传入函数的消费逻辑
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
public class ConsumerTest {
public static void main(String[] args) {
Consumer<String> consumer1 = s -> {
System.out.println(s + ",我是消费者1");
};
Consumer<String> consumer2 = s -> {
System.out.println(s + ",我是消费者2");
};
consumer1.accept("铁甲小宝");
System.out.println("################");
consumer1.andThen(consumer2).accept("铁甲小宝");
}
}
执行输出:
铁甲小宝,我是消费者1
################
铁甲小宝,我是消费者1
铁甲小宝,我是消费者2
断言函数,接受1个输入参数,返回1个布尔值结果。
@FunctionalInterface
public interface Predicate<T> {
// 对输入进行断言
boolean test(T t);
// 函数并操作
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);
}
// 函数或操作
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);
}
// 取反
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}
public class PredicateTest {
public static void main(String[] args) {
// 断言输入值是否大于10
Predicate<Integer> isSuperTen = i -> {return i>10;};
System.out.println(isSuperTen.test(11));
System.out.println(isSuperTen.test(6));
// 取反,断言输入值是否不大于10
Predicate<Integer> negate = isSuperTen.negate();
System.out.println(negate.test(6));
// 断言输入值是否大于20
Predicate<Integer> isLowerTwenty = i -> {return i<20;};
// 断言15是否>10且<20
System.out.println(isSuperTen.and(isLowerTwenty).test(15));
// 断言21是否>10且<20
System.out.println(isSuperTen.and(isLowerTwenty).test(21));
// 断言21是否>10或<20
System.out.println(isSuperTen.or(isLowerTwenty).test(21));
}
}
执行输出:
true
false
true
true
false
true
接受1个入参T和U,并返回结果R。
@FunctionalInterface
public interface BiFunction<T, U, R> {
// 根据输入t和u,转化为输出r
R apply(T t, U u);
// 先执行本函数,再执行参数传入的函数
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(apply(t, u));
}
}
public class BiFunctionTest {
public static void main(String[] args) {
BiFunction<String, Integer, String> biFunction = (key, value) -> {return (key + ":" + String.valueOf(value));};
String key = "age";
Integer value = 18;
System.out.println(biFunction.apply(key, value));
Function<String, String> afterFunction = s -> {
System.out.println("执行后继函数,添加前缀***");
return "***-" + s;
};
System.out.println(biFunction.andThen(afterFunction).apply(key, value));
}
}
执行输出:
age:18
执行后继函数,添加前缀***
***-age:18
代表了1个接受2个输入参数的操作,并且不返回任何结果。
@FunctionalInterface
public interface BiConsumer<T, U> {
// 消费2个输入t和u
void accept(T t, U u);
// 先执行该函数的消费逻辑,再执行传入函数的消费逻辑
default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {
Objects.requireNonNull(after);
return (l, r) -> {
accept(l, r);
after.accept(l, r);
};
}
public class BiConsumerTest {
public static void main(String[] args) {
BiConsumer<String, Integer> biConsumer1 = (s, i) -> {
System.out.println("我是消费逻辑1" + "," + s + "," + String.valueOf(i+10));
};
BiConsumer<String, Integer> biConsumer2 = (s, i) -> {
System.out.println("我是消费逻辑2" + "," + s + "," + String.valueOf(i*3));
};
biConsumer1.accept("铁甲小宝", 6);
System.out.println("###########");
biConsumer1.andThen(biConsumer2).accept("铁甲小宝", 6);
}
}
执行输出:
我是消费逻辑1,铁甲小宝,16
###########
我是消费逻辑1,铁甲小宝,16
我是消费逻辑2,铁甲小宝,18
对2个输入参数T和U进行断言,返回1个布尔值输出。
@FunctionalInterface
public interface BiPredicate<T, U> {
// 断言输入t和u
boolean test(T t, U u);
// 并操作
default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) {
Objects.requireNonNull(other);
return (T t, U u) -> test(t, u) && other.test(t, u);
}
// 取反
default BiPredicate<T, U> negate() {
return (T t, U u) -> !test(t, u);
}
// 或操作
default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) {
Objects.requireNonNull(other);
return (T t, U u) -> test(t, u) || other.test(t, u);
}
}
public class BiPredicateTest {
public static void main(String[] args) {
// 判断输入1是否大于10,且输入2小于20
BiPredicate<String, Integer> biPredicate = (s, i) -> {
return Integer.valueOf(s) > 10 && i < 20;
};
System.out.println(biPredicate.test("15", 16));
System.out.println(biPredicate.test("15", 21));
System.out.println(biPredicate.test("6", 21));
}
}
执行输出:
true
false
false
其他函数接口基本原理类似,不再赘述。
之所以今天讲解一下JDK8的函数式编程,主要是为后续的Flink源码解析系列做一些前置知识储备,因为Flink源码里有大量的函数式接口实践。
本文到此结束,谢谢阅读!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。