
函数式接口(Function Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口又称为:功能接口。
功能接口为 Lambda 表达式和方法引用(用双冒号 ::来进行方法调用)提供目标类型!每个功能接口都有一个抽象方法,称为该功能接口的功能方法。Lambda 表达式的参数和返回类型要与功能方法的参数和返回值类型匹配或适配。
JDK8 开始,为函数式接口引入了一个新注解:@FunctionalInterface,主要用于编译级错误检查。
当接口加上了此注解后,如果接口不符合函数式接口的定义,则会报错。
注意:此注解不是编译器将接口识别为功能接口的必要条件,仅仅是帮助捕获设计意图并获得编译器帮助识别意外违反设计意图的帮助。
eg:
@FunctionalInterface
public interface HelloWorldService {
void sayHello(String msg);
}@FunctionalInterface
public interface HelloWorldService {
void sayHello(String msg);
void sayWorld();
}接口中只需要有且仅有一个抽象方法即可称为:函数式接口。此接口中可以存在默认方法、静态方法、Object 包下的 public 方法。下面,我将分别演示一遍。
函数式接口里面是可以包含默认方法的,因为默认方法不是抽象方法,有一个默认实现,所以是符合函数式接口的定义。
@FunctionalInterface
public interface HelloWorldService {
void sayHello(String msg);
default void doSomeWork1() {
// Method body
System.sout.println("做作业");
}
default void doSomeWork2() {
// Method body
System.sout.println("打游戏");
}
}函数式接口里面是可以包含静态方法的,因为静态方法不是抽象方法,是一个已经实现了的方法,所以是符合函数式接口的定义。
@FunctionalInterface
public interface HelloWorldService {
void sayHello(String msg);
static void printHello() {
System.out.println("Hello");
}
}Java.Lang.Object类中的 public 方法函数式接口是可以包含 Object 类里的 public 方法。因为每一个函数式接口的实现,最顶层都默认继承了 Object 类,包含了来自 java.lang.object类中对这些抽象方法的实现
@FunctionalInterface
public interface HelloWorldService {
void sayHello(String msg);
// Object 类中的方法
@Override
boolean equals(Object obj);
}序号 | 接口名 | 描述 |
|---|---|---|
1 | Function<T,R> | 接收一个参数并返回结果的函数 |
2 | BiFunction<T,U,R> | 接受两个参数并返回结果的函数 |
3 | DoubleFunction<R> | 接收一个 double 类型的参数并返回结果的函数 |
4 | DoubleToIntFunction | 接收一个 double 类型的参数并返回 int 结果的函数 |
5 | DoubleToLongFunction | 接收一个 double 类型的参数并返回 long 结果的函数 |
6 | IntFunction<R> | 接收一个 int 类型的参数并返回结果的函数 |
7 | IntToDoubleFunction | 接收一个 int 类型的参数并返回 double 结果的函数 |
8 | IntToLongFunction | 接收一个 int 类型的参数并返回 long 结果的函数 |
9 | LongFunction<R> | 接收一个 long 类型的参数并返回结果的函数 |
10 | LongToDoubleFunction | 接收一个 long 类型的参数并返回 double 结果的函数 |
11 | LongToIntFunction | 接收一个 long 类型的参数并返回 int 结果的函数 |
12 | ToDoubleBiFunction<T,U> | 接收两个参数并返回 double 结果的函数 |
13 | ToDoubleFunction<T> | 接收一个参数并返回 double 结果的函数 |
14 | ToIntBiFunction<T,U> | 接收两个参数并返回 int 结果的函数 |
15 | ToIntFunction<T> | 接收一个参数并返回 int 结果的函数 |
16 | ToLongBiFunction<T,U> | 接收两个参数并返回 long 结果的函数 |
17 | ToLongFunction<T> | 接收一个参数并返回 long 结果的函数 |
下面,博主将介绍几种常见Function函数的使用方法。
源码:
@FunctionalInterface
public interface Function<T, R> {
/**
* 将形参 t 作为参数传递到此函数中
*
* @param t 函数参数
* @return 函数结果
*/
R apply(T t);
/**
* 返回一个组合函数,该函数首先将 before 函数应用于输入,然后再将此函数应用于结果。如果
* 任一函数的求值抛出异常,则会转发到该组合函数的调用者
*
* @param before 应用此函数之前要应用的函数
* @return 先应用 before 函数,然后应用此函数的组合函数
* @throws NullPointerException
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* 返回一个组合函数,该函数首先将此函数应用于其输入,然后将 after 函数应用于结果。
* 如果对任一函数的求值抛出异常,则将其转发给组合函数的调用者。
*
* @param after 应用此函数后要应用的函数
* @return 一个组合函数,首先应用此函数,然后应用 after 函数
* @throws NullPointerException
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* 返回一个始终返回其输入参数的函数。
*
* @return 始终返回其输入参数的函数
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}方法:
接口方法 | 方法描述 |
|---|---|
R apply(T t) | 将 t 参数应用到函数中 |
Function<T, V> andThen(Function<? super R, ? extends V> after) | 返回一个组合函数,将该函数结果应用到 after 函数中 |
Function<V, R> compose(Function<? super V, ? extends T> before) | 返回一个组合函数,首先将入参应用于 before 函数中,再将 before 函数结果应用到该函数中 |
Function<T, T> identity() | 返回一个始终返回该输入参数的函数 |
方法示例:
R apply(T t)@PostMapping(value = "/findAd")
public MerchantResult findAd(@RequestBody MerchantRequest request) {
return handleMerchantResult(request, currencyService::findAd);
}
/**
* 统一包装返回结果
*
* @param request 请求实体对象
* @param serviceFunction 服务函数
* @return 统一返回结果对象
*/
private MerchantResult handleMerchantResult(MerchantRequest request, Function<MerchantRequest, MerchantResult> serviceFunction) {
try {
// 将前端传递过来的参数应用到对应service层的方法中
return serviceFunction.apply(request);
} catch (ServiceException e) {
return MerchantResult.error(request.getMerchantId(), request.getRequestId(), e.getMessage());
}
}Function<String, String> function = a -> a + " Jack!";
System.out.println(function.apply("Hello")); // Hello Jack!Function<T, V> andThen(Function<? super R, ? extends V> after)Function<String, String> function = a -> a + " Jack!";
Function<String, String> function1 = a -> a + " Bob!";
String greet = function.andThen(function1).apply("Hello");
System.out.println(greet); // Hello Jack! Bob!Function<V, R> compose(Function<? super V, ? extends T> before)Function<String, String> function = a -> a + " Jack!";
Function<String, String> function1 = a -> a + " Bob!";
String greet = function.compose(function1).apply("Hello");
System.out.println(greet); // Hello Bob! Jack!Function<T, T> identity()// 这是 identity() 方法最常见的使用场景:将 List 转换为 Map
List<Student> list = new ArrayList<>();
list.stream().collect(Collectors.toMap(Student::getStudentId, Function.identity()));源码:
@FunctionalInterface
public interface BiFunction<T, U, R> {
/**
* 将此函数应用于给定的两个参数。
*
* @param t 第一个函数参数
* @param u 第二个函数参数
* @return 函数结果
*/
R apply(T t, U u);
/**
* 返回一个组合函数,该函数首先将此函数应用于其输入,然后将 after 函数应用于结果。
* 如果对任一函数的求值抛出异常,则将其转发给组合函数的调用者。
*
* @param after 应用此函数后要应用的函数
* @return 一个组合函数,首先应用此函数,然后应用 after 函数
* @throws NullPointerException
*/
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));
}
}方法:
接口方法 | 方法描述 |
|---|---|
R apply(T t, U u) | 将两个参数应用于函数执行 |
BiFunction<T,U,V> andThen(Function<? super R,? extends V> after) | 返回一个组合函数,after函数应用于该函数之后 |
方法示例:
R apply(T t, U u)BiFunction<String, String, String> biFunction = (a, b) -> a + b;
System.out.println(biFunction.apply("Hello ", "Jack!")); // Hello Jack!BiFunction<T,U,V> andThen(Function<? super R,? extends V> after)BiFunction<String, String, String> biFunction = (a, b) -> a + b;
Function<String, String> function = (a) -> a + "!!!";
System.out.println(biFunction.andThen(function).apply("Hello", "Jack")); // Hello Jack!!!源码:
@FunctionalInterface
public interface DoubleFunction<R> {
/**
* 根据给定 double 类型的参数执行函数
*
* @param value 函数参数
* @return 函数结果
*/
R apply(double value);方法:
接口方法 | 方法描述 |
|---|---|
R apply(double value) | 将给定Double类型的参数应用于函数 |
方法示例:
R apply(T t, U u)DoubleFunction<String> doubleFunction = doub -> "结果:" + doub;
System.out.println(doubleFunction.apply(1.6)); // 结果:1.6源码:
@FunctionalInterface
public interface DoubleToIntFunction {
// 将给定的 double 类型的数据转换成 int 类型
int applyAsInt(double var1);
}方法:
接口方法 | 方法描述 |
|---|---|
int applyAsInt(double value) | 将给定Double类型参数应用于函数,并转换成Int类型 |
方法示例:
int applyAsInt(double value)DoubleToIntFunction doubleToIntFunction = doub -> {
System.out.println("值为:" + doub);
return doub.intValue();
};
System.out.println(doubleToIntFunction.applyAsInt(1.2)); // 值为:1.2 1源码:
@FunctionalInterface
public interface ToDoubleBiFunction<T, U> {
/**
* 将此函数应用于给定的参数。
*
* @param t 第一个函数参数
* @param u 第二个函数参数
* @return 函数结果
*/
double applyAsDouble(T t, U u);
}方法:
接口方法 | 方法描述 |
|---|---|
double applyAsDouble(T value) | 根据给定的两个参数执行函数 |
方法示例:
double applyAsDouble(T value)ToDoubleBiFunction<Long, Float> toDoubleBiFunction = (a1, a2) -> a1.doubleValue() + a2.doubleValue();
System.out.println(toDoubleBiFunction.applyAsDouble(11L, 235.5f)); // 246.5源码:
@FunctionalInterface
public interface ToDoubleFunction<T> {
/**
* 将此函数应用于给定的参数
*
* @param value 函数参数
* @return 函数结果
*/
double applyAsDouble(T value);
}方法:
接口方法 | 方法描述 |
|---|---|
double applyAsDouble(T value) | 根据给定的一个参数执行函数 |
方法示例:
double applyAsDouble(T value)ToDoubleFunction<Float> toDoubleFunction = floa -> floa.doubleValue();
System.out.println(toDoubleFunction.applyAsDouble(12315f)); // 12315.0序号 | 接口 | 描述 |
|---|---|---|
1 | Consumer<T> | 提供一个 T 类型的输入参数,不返回执行结果 |
2 | BiConsumer<T,U> | 提供两个自定义类型的输入参数,不返回执行结果 |
3 | DoubleConsumer | 表示接受单个 Double 类型参数,但不返回结果的操作 |
4 | IntConsumer | 表示接受单个 Int 类型参数,但不返回结果的操作 |
5 | LongConsumer | 表示接受单个 Long 类型参数,但不返回结果的操作 |
6 | ObjDoubleConsumer<T> | 表示接受 Object 类型和 Double 类型参数,但是不返回任何操作结果 |
7 | ObjIntConsumer<T> | 表示接受 Object 类型和 Int 类型,但是不返回任何操作结果 |
8 | ObjLongConsumer<T> | 表示接受 Object 类型和 Long 类型,但是不返回任何操作结果 |
下面,博主将介绍几种常见Consumer函数的使用方法。
源码:
@FunctionalInterface
public interface Consumer<T> {
/**
* 对给定的参数执行此操作
*
* @param t 输入参数
*/
void accept(T t);
/**
* 返回一个组合的Consumer,该Consumer按顺序执行此操作,然后执行after操作。
* 如果执行任一操作都会引发异常,则会将其转发给组合操作的调用者。如果执行此操作会引发异常,则不会执行 after 操作。
*
* @param after 此操作后要执行的操作
* @return 一个组合的消费者,按顺序执行此操作,然后执行 after 操作
* @throws NullPointerException
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}方法:
接口方法 | 方法描述 |
|---|---|
void accept(T t, U u) | 对给定的参数执行操作 |
default Consumer andThen(Consumer<? super T> after) | 返回一个组合函数,after 将会在该函数执行之后执行 |
方法示例:
void accept(T t, U u)StringBuilder sb = new StringBuilder("Hello ");
Consumer<StringBuilder> consumer = (str) -> str.append("Jack!");
consumer.accept(sb);
System.out.println(sb.toString()); // Hello Jack!default Consumer andThen(Consumer<? super T> after)StringBuilder sb = new StringBuilder("Hello");
Consumer<StringBuilder> consumer = (str) -> str.append(" Jack!");
Consumer<StringBuilder> consumer1 = (str) -> str.append(" Bob!");
consumer.andThen(consumer1).accept(sb);
System.out.println(sb.toString()); // Hello Jack! Bob!源码:
@FunctionalInterface
public interface BiConsumer<T, U> {
/**
* 对给定的参数执行此操作
*
* @param t 第一个输入参数
* @param u 第二个输入参数
*/
void accept(T t, U u);
/**
* 返回一个组合的BiConsumer,该BiConsumer按顺序执行此操作,然后执行after操作。
* 如果执行任一操作都会引发异常,则会将其转发给组合操作的调用者。如果执行此操作会引发异常,则不会执行 after 操作。
*
* @param after 此操作后要执行的操作
* @return a 一个组合的 BiConsumer,按顺序执行此操作,然后执行 after 操作
* @throws NullPointerException
*/
default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {
Objects.requireNonNull(after);
return (l, r) -> {
accept(l, r);
after.accept(l, r);
};
}
}方法:
接口方法 | 方法描述 |
|---|---|
void accept(T t, U u) | 对给定的参数执行操作 |
default BiConsumer<T,U> andThen(BiConsumer<? super T,? super U> after) | 返回一个组合函数,after 将会在该函数执行之后执行 |
方法示例:
void accept(T t, U u)StringBuilder sb = new StringBuilder();
BiConsumer<String, String> biConsumer = (a, b) -> {
sb.append(a);
sb.append(b);
};
biConsumer.accept("Hello ", "Jack!");
System.out.println(sb.toString()); // Hello Jack!default BiConsumer<T,U> andThen(BiConsumer<? super T,? super U> after)StringBuilder sb = new StringBuilder();
BiConsumer<String, String> biConsumer = (a, b) -> {
sb.append(a);
sb.append(b);
};
BiConsumer<String, String> biConsumer1 = (a, b) -> {
System.out.println(a + b);
};
biConsumer.andThen(biConsumer1).accept("Hello", " Jack!"); // Hello Jack!源码:
@FunctionalInterface
public interface DoubleConsumer {
/**
* 对给定的参数执行此操作
*
* @param value 输入参数
*/
void accept(double value);
/**
* 返回一个组合的DoubleConsumer,它按顺序执行此操作,然后执行after操作。
* 如果执行任一操作都会引发异常,则会将其转发给组合操作的调用者。如果执行此操作会引发异常,则不会执行 after 操作。
*
* @param after 此操作后要执行的操作
* @return 一个组合的DoubleConsumer,按顺序执行此操作,然后执行 after 操作
* @throws NullPointerException
*/
default DoubleConsumer andThen(DoubleConsumer after) {
Objects.requireNonNull(after);
return (double t) -> { accept(t); after.accept(t); };
}方法:
接口方法 | 方法描述 |
|---|---|
void accept(double value) | 对给定的参数执行操作 |
default DoubleConsumer andThen(DoubleConsumer after) | 返回一个组合函数,after 在该函数执行之后执行 |
方法示例:
void accept(double value)DoubleConsumer doubleConsumer = System.out::println;
doubleConsumer.accept(1.3); // 1.3default DoubleConsumer andThen(DoubleConsumer after)DoubleConsumer doubleConsumer = (a) -> Integer.parseInt(a);
DoubleConsumer doubleConsumer1 = System.out::println;
doubleConsumer.andThen(doubleConsumer1).accept(1.3); // 1源码:
@FunctionalInterface
public interface ObjDoubleConsumer<T> {
/**
* 对给定的参数执行此操作
*
* @param t 第一个输入参数
* @param value 第二个输入参数
*/
void accept(T t, double value);
}方法:
接口方法 | 方法描述 |
|---|---|
void accept(double value) | 对给定的参数执行操作 |
方法示例:
void accept(double value)ObjDoubleConsumer<String> doubleConsumer = (obj, doub)
-> System.out.println(obj + doub);
doubleConsumer.accept("金额:", 222.66); // 金额:222.66这是第一篇文章,因为内容比较多,所以博主分成了两篇文章发布。第二篇文章里面有介绍Predicate、Supplier、Operator这三个函数式接口的使用。敬请期待~