Java中的函数式接口详解(一)

  • 2026-07-23 03:19:11

1. 函数式接口1.1. 定义函数式接口(Function Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

函数式接口又称为:功能接口。

功能接口为 Lambda 表达式和方法引用(用双冒号 ::来进行方法调用)提供目标类型!每个功能接口都有一个抽象方法,称为该功能接口的功能方法。Lambda 表达式的参数和返回类型要与功能方法的参数和返回值类型匹配或适配。

JDK8 开始,为函数式接口引入了一个新注解:@FunctionalInterface,主要用于编译级错误检查。

当接口加上了此注解后,如果接口不符合函数式接口的定义,则会报错。

注意:此注解不是编译器将接口识别为功能接口的必要条件,仅仅是帮助捕获设计意图并获得编译器帮助识别意外违反设计意图的帮助。

eg:

代码语言:javascript复制@FunctionalInterface

public interface HelloWorldService {

void sayHello(String msg);

}代码语言:javascript复制@FunctionalInterface

public interface HelloWorldService {

void sayHello(String msg);

void sayWorld();

}接口中只需要有且仅有一个抽象方法即可称为:函数式接口。此接口中可以存在默认方法、静态方法、Object 包下的 public 方法。下面,我将分别演示一遍。

1.2. 允许存在默认方法函数式接口里面是可以包含默认方法的,因为默认方法不是抽象方法,有一个默认实现,所以是符合函数式接口的定义。

代码语言:javascript复制@FunctionalInterface

public interface HelloWorldService {

void sayHello(String msg);

default void doSomeWork1() {

// Method body

System.sout.println("做作业");

}

default void doSomeWork2() {

// Method body

System.sout.println("打游戏");

}

}1.3. 允许存在静态方法函数式接口里面是可以包含静态方法的,因为静态方法不是抽象方法,是一个已经实现了的方法,所以是符合函数式接口的定义。

代码语言:javascript复制@FunctionalInterface

public interface HelloWorldService {

void sayHello(String msg);

static void printHello() {

System.out.println("Hello");

}

}1.4. 允许存在Java.Lang.Object类中的 public 方法函数式接口是可以包含 Object 类里的 public 方法。因为每一个函数式接口的实现,最顶层都默认继承了 Object 类,包含了来自 java.lang.object类中对这些抽象方法的实现

代码语言:javascript复制@FunctionalInterface

public interface HelloWorldService {

void sayHello(String msg);

// Object 类中的方法

@Override

boolean equals(Object obj);

}2. Function 函数接口2.1. 分类序号

接口名

描述

1

Function

接收一个参数并返回结果的函数

2

BiFunction

接受两个参数并返回结果的函数

3

DoubleFunction

接收一个 double 类型的参数并返回结果的函数

4

DoubleToIntFunction

接收一个 double 类型的参数并返回 int 结果的函数

5

DoubleToLongFunction

接收一个 double 类型的参数并返回 long 结果的函数

6

IntFunction

接收一个 int 类型的参数并返回结果的函数

7

IntToDoubleFunction

接收一个 int 类型的参数并返回 double 结果的函数

8

IntToLongFunction

接收一个 int 类型的参数并返回 long 结果的函数

9

LongFunction

接收一个 long 类型的参数并返回结果的函数

10

LongToDoubleFunction

接收一个 long 类型的参数并返回 double 结果的函数

11

LongToIntFunction

接收一个 long 类型的参数并返回 int 结果的函数

12

ToDoubleBiFunction

接收两个参数并返回 double 结果的函数

13

ToDoubleFunction

接收一个参数并返回 double 结果的函数

14

ToIntBiFunction

接收两个参数并返回 int 结果的函数

15

ToIntFunction

接收一个参数并返回 int 结果的函数

16

ToLongBiFunction

接收两个参数并返回 long 结果的函数

17

ToLongFunction

接收一个参数并返回 long 结果的函数

下面,博主将介绍几种常见Function函数的使用方法。

2.2. Function源码:

代码语言:javascript复制@FunctionalInterface

public interface Function {

/**

* 将形参 t 作为参数传递到此函数中

*

* @param t 函数参数

* @return 函数结果

*/

R apply(T t);

/**

* 返回一个组合函数,该函数首先将 before 函数应用于输入,然后再将此函数应用于结果。如果

* 任一函数的求值抛出异常,则会转发到该组合函数的调用者

*

* @param before 应用此函数之前要应用的函数

* @return 先应用 before 函数,然后应用此函数的组合函数

* @throws NullPointerException

*/

default Function compose(Function before) {

Objects.requireNonNull(before);

return (V v) -> apply(before.apply(v));

}

/**

* 返回一个组合函数,该函数首先将此函数应用于其输入,然后将 after 函数应用于结果。

* 如果对任一函数的求值抛出异常,则将其转发给组合函数的调用者。

*

* @param after 应用此函数后要应用的函数

* @return 一个组合函数,首先应用此函数,然后应用 after 函数

* @throws NullPointerException

*/

default Function andThen(Function after) {

Objects.requireNonNull(after);

return (T t) -> after.apply(apply(t));

}

/**

* 返回一个始终返回其输入参数的函数。

*

* @return 始终返回其输入参数的函数

*/

static Function identity() {

return t -> t;

}

}方法:

接口方法

方法描述

R apply(T t)

将 t 参数应用到函数中

Function andThen(Function after)

返回一个组合函数,将该函数结果应用到 after 函数中

Function compose(Function before)

返回一个组合函数,首先将入参应用于 before 函数中,再将 before 函数结果应用到该函数中

Function identity()

返回一个始终返回该输入参数的函数

方法示例:

R apply(T t)代码语言:javascript复制@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 serviceFunction) {

try {

// 将前端传递过来的参数应用到对应service层的方法中

return serviceFunction.apply(request);

} catch (ServiceException e) {

return MerchantResult.error(request.getMerchantId(), request.getRequestId(), e.getMessage());

}

}代码语言:javascript复制Function function = a -> a + " Jack!";

System.out.println(function.apply("Hello")); // Hello Jack!Function andThen(Function after)代码语言:javascript复制Function function = a -> a + " Jack!";

Function function1 = a -> a + " Bob!";

String greet = function.andThen(function1).apply("Hello");

System.out.println(greet); // Hello Jack! Bob!Function compose(Function before)代码语言:javascript复制Function function = a -> a + " Jack!";

Function function1 = a -> a + " Bob!";

String greet = function.compose(function1).apply("Hello");

System.out.println(greet); // Hello Bob! Jack!Function identity()代码语言:javascript复制// 这是 identity() 方法最常见的使用场景:将 List 转换为 Map

List list = new ArrayList<>();

list.stream().collect(Collectors.toMap(Student::getStudentId, Function.identity()));2.3. BiFunction源码:

代码语言:javascript复制@FunctionalInterface

public interface BiFunction {

/**

* 将此函数应用于给定的两个参数。

*

* @param t 第一个函数参数

* @param u 第二个函数参数

* @return 函数结果

*/

R apply(T t, U u);

/**

* 返回一个组合函数,该函数首先将此函数应用于其输入,然后将 after 函数应用于结果。

* 如果对任一函数的求值抛出异常,则将其转发给组合函数的调用者。

*

* @param after 应用此函数后要应用的函数

* @return 一个组合函数,首先应用此函数,然后应用 after 函数

* @throws NullPointerException

*/

default BiFunction andThen(Function after) {

Objects.requireNonNull(after);

return (T t, U u) -> after.apply(apply(t, u));

}

}方法:

接口方法

方法描述

R apply(T t, U u)

将两个参数应用于函数执行

BiFunction andThen(Function after)

返回一个组合函数,after函数应用于该函数之后

方法示例:

R apply(T t, U u)代码语言:javascript复制BiFunction biFunction = (a, b) -> a + b;

System.out.println(biFunction.apply("Hello ", "Jack!")); // Hello Jack!BiFunction andThen(Function after)代码语言:javascript复制BiFunction biFunction = (a, b) -> a + b;

Function function = (a) -> a + "!!!";

System.out.println(biFunction.andThen(function).apply("Hello", "Jack")); // Hello Jack!!!2.4. DoubleFunction源码:

代码语言:javascript复制@FunctionalInterface

public interface DoubleFunction {

/**

* 根据给定 double 类型的参数执行函数

*

* @param value 函数参数

* @return 函数结果

*/

R apply(double value);方法:

接口方法

方法描述

R apply(double value)

将给定Double类型的参数应用于函数

方法示例:

R apply(T t, U u)代码语言:javascript复制DoubleFunction doubleFunction = doub -> "结果:" + doub;

System.out.println(doubleFunction.apply(1.6)); // 结果:1.62.5. DoubleToIntFunction源码:

代码语言:javascript复制@FunctionalInterface

public interface DoubleToIntFunction {

// 将给定的 double 类型的数据转换成 int 类型

int applyAsInt(double var1);

}方法:

接口方法

方法描述

int applyAsInt(double value)

将给定Double类型参数应用于函数,并转换成Int类型

方法示例:

int applyAsInt(double value)代码语言:javascript复制DoubleToIntFunction doubleToIntFunction = doub -> {

System.out.println("值为:" + doub);

return doub.intValue();

};

System.out.println(doubleToIntFunction.applyAsInt(1.2)); // 值为:1.2 12.6. ToDoubleBiFunction源码:

代码语言:javascript复制@FunctionalInterface

public interface ToDoubleBiFunction {

/**

* 将此函数应用于给定的参数。

*

* @param t 第一个函数参数

* @param u 第二个函数参数

* @return 函数结果

*/

double applyAsDouble(T t, U u);

}方法:

接口方法

方法描述

double applyAsDouble(T value)

根据给定的两个参数执行函数

方法示例:

double applyAsDouble(T value)代码语言:javascript复制ToDoubleBiFunction toDoubleBiFunction = (a1, a2) -> a1.doubleValue() + a2.doubleValue();

System.out.println(toDoubleBiFunction.applyAsDouble(11L, 235.5f)); // 246.52.7. ToDoubleFunction源码:

代码语言:javascript复制@FunctionalInterface

public interface ToDoubleFunction {

/**

* 将此函数应用于给定的参数

*

* @param value 函数参数

* @return 函数结果

*/

double applyAsDouble(T value);

}方法:

接口方法

方法描述

double applyAsDouble(T value)

根据给定的一个参数执行函数

方法示例:

double applyAsDouble(T value)代码语言:javascript复制ToDoubleFunction toDoubleFunction = floa -> floa.doubleValue();

System.out.println(toDoubleFunction.applyAsDouble(12315f)); // 12315.03. Consumer 消费者接口3.1. 分类序号

接口

描述

1

Consumer

提供一个 T 类型的输入参数,不返回执行结果

2

BiConsumer

提供两个自定义类型的输入参数,不返回执行结果

3

DoubleConsumer

表示接受单个 Double 类型参数,但不返回结果的操作

4

IntConsumer

表示接受单个 Int 类型参数,但不返回结果的操作

5

LongConsumer

表示接受单个 Long 类型参数,但不返回结果的操作

6

ObjDoubleConsumer

表示接受 Object 类型和 Double 类型参数,但是不返回任何操作结果

7

ObjIntConsumer

表示接受 Object 类型和 Int 类型,但是不返回任何操作结果

8

ObjLongConsumer

表示接受 Object 类型和 Long 类型,但是不返回任何操作结果

下面,博主将介绍几种常见Consumer函数的使用方法。

3.2. Consumer源码:

代码语言:javascript复制@FunctionalInterface

public interface Consumer {

/**

* 对给定的参数执行此操作

*

* @param t 输入参数

*/

void accept(T t);

/**

* 返回一个组合的Consumer,该Consumer按顺序执行此操作,然后执行after操作。

* 如果执行任一操作都会引发异常,则会将其转发给组合操作的调用者。如果执行此操作会引发异常,则不会执行 after 操作。

*

* @param after 此操作后要执行的操作

* @return 一个组合的消费者,按顺序执行此操作,然后执行 after 操作

* @throws NullPointerException

*/

default Consumer andThen(Consumer after) {

Objects.requireNonNull(after);

return (T t) -> { accept(t); after.accept(t); };

}

}方法:

接口方法

方法描述

void accept(T t, U u)

对给定的参数执行操作

default Consumer andThen(Consumer after)

返回一个组合函数,after 将会在该函数执行之后执行

方法示例:

void accept(T t, U u)代码语言:javascript复制StringBuilder sb = new StringBuilder("Hello ");

Consumer consumer = (str) -> str.append("Jack!");

consumer.accept(sb);

System.out.println(sb.toString()); // Hello Jack!default Consumer andThen(Consumer after)代码语言:javascript复制StringBuilder sb = new StringBuilder("Hello");

Consumer consumer = (str) -> str.append(" Jack!");

Consumer consumer1 = (str) -> str.append(" Bob!");

consumer.andThen(consumer1).accept(sb);

System.out.println(sb.toString()); // Hello Jack! Bob!3.3. BiConsumer源码:

代码语言:javascript复制@FunctionalInterface

public interface BiConsumer {

/**

* 对给定的参数执行此操作

*

* @param t 第一个输入参数

* @param u 第二个输入参数

*/

void accept(T t, U u);

/**

* 返回一个组合的BiConsumer,该BiConsumer按顺序执行此操作,然后执行after操作。

* 如果执行任一操作都会引发异常,则会将其转发给组合操作的调用者。如果执行此操作会引发异常,则不会执行 after 操作。

*

* @param after 此操作后要执行的操作

* @return a 一个组合的 BiConsumer,按顺序执行此操作,然后执行 after 操作

* @throws NullPointerException

*/

default BiConsumer andThen(BiConsumer after) {

Objects.requireNonNull(after);

return (l, r) -> {

accept(l, r);

after.accept(l, r);

};

}

}方法:

接口方法

方法描述

void accept(T t, U u)

对给定的参数执行操作

default BiConsumer andThen(BiConsumer after)

返回一个组合函数,after 将会在该函数执行之后执行

方法示例:

void accept(T t, U u)代码语言:javascript复制StringBuilder sb = new StringBuilder();

BiConsumer biConsumer = (a, b) -> {

sb.append(a);

sb.append(b);

};

biConsumer.accept("Hello ", "Jack!");

System.out.println(sb.toString()); // Hello Jack!default BiConsumer andThen(BiConsumer after)代码语言:javascript复制StringBuilder sb = new StringBuilder();

BiConsumer biConsumer = (a, b) -> {

sb.append(a);

sb.append(b);

};

BiConsumer biConsumer1 = (a, b) -> {

System.out.println(a + b);

};

biConsumer.andThen(biConsumer1).accept("Hello", " Jack!"); // Hello Jack!3.4. DoubleConsumer源码:

代码语言:javascript复制@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)代码语言:javascript复制DoubleConsumer doubleConsumer = System.out::println;

doubleConsumer.accept(1.3); // 1.3default DoubleConsumer andThen(DoubleConsumer after)代码语言:javascript复制DoubleConsumer doubleConsumer = (a) -> Integer.parseInt(a);

DoubleConsumer doubleConsumer1 = System.out::println;

doubleConsumer.andThen(doubleConsumer1).accept(1.3); // 13.5. ObjDoubleConsumer源码:

代码语言:javascript复制@FunctionalInterface

public interface ObjDoubleConsumer {

/**

* 对给定的参数执行此操作

*

* @param t 第一个输入参数

* @param value 第二个输入参数

*/

void accept(T t, double value);

}方法:

接口方法

方法描述

void accept(double value)

对给定的参数执行操作

方法示例:

void accept(double value)代码语言:javascript复制ObjDoubleConsumer doubleConsumer = (obj, doub)

-> System.out.println(obj + doub);

doubleConsumer.accept("金额:", 222.66); // 金额:222.66后话:这是第一篇文章,因为内容比较多,所以博主分成了两篇文章发布。第二篇文章里面有介绍Predicate、Supplier、Operator这三个函数式接口的使用。敬请期待~

友情链接
Copyright © 2022 极限竞技游戏活动前线 All Rights Reserved.