首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Java中的函数式接口详解(一)

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

作者头像
CodeSuc
发布2025-11-03 17:41:44
发布2025-11-03 17:41:44
1300
举报

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<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函数的使用方法。

2.2. Function<T,R>

源码:

代码语言:javascript
复制
@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()

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

方法示例:

  1. 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<MerchantRequest, MerchantResult> serviceFunction) {
    try {
        // 将前端传递过来的参数应用到对应service层的方法中
        return serviceFunction.apply(request);  
    } catch (ServiceException e) {
        return MerchantResult.error(request.getMerchantId(), request.getRequestId(), e.getMessage());
    }
}
代码语言:javascript
复制
Function<String, String> function = a -> a + " Jack!";
System.out.println(function.apply("Hello")); // Hello Jack!
  1. Function<T, V> andThen(Function<? super R, ? extends V> after)
代码语言:javascript
复制
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!
  1. Function<V, R> compose(Function<? super V, ? extends T> before)
代码语言:javascript
复制
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!
  1. Function<T, T> identity()
代码语言:javascript
复制
// 这是 identity() 方法最常见的使用场景:将 List 转换为 Map
List<Student> list = new ArrayList<>();
list.stream().collect(Collectors.toMap(Student::getStudentId, Function.identity()));

2.3. BiFunction<T,U,R>

源码:

代码语言:javascript
复制
@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函数应用于该函数之后

方法示例:

  1. R apply(T t, U u)
代码语言:javascript
复制
BiFunction<String, String, String> biFunction = (a, b) -> a + b;
System.out.println(biFunction.apply("Hello ", "Jack!")); // Hello Jack!
  1. BiFunction<T,U,V> andThen(Function<? super R,? extends V> after)
代码语言:javascript
复制
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!!!

2.4. DoubleFunction<R>

源码:

代码语言:javascript
复制
@FunctionalInterface
public interface DoubleFunction<R> {

    /**
     * 根据给定 double 类型的参数执行函数
     *
     * @param value 函数参数
     * @return 函数结果
     */
    R apply(double value);

方法:

接口方法

方法描述

R apply(double value)

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

方法示例:

  1. R apply(T t, U u)
代码语言:javascript
复制
DoubleFunction<String> doubleFunction = doub -> "结果:" + doub;
System.out.println(doubleFunction.apply(1.6)); // 结果:1.6

2.5. DoubleToIntFunction

源码:

代码语言:javascript
复制
@FunctionalInterface
public interface DoubleToIntFunction {

    // 将给定的 double 类型的数据转换成 int 类型
    int applyAsInt(double var1);
}

方法:

接口方法

方法描述

int applyAsInt(double value)

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

方法示例:

  1. int applyAsInt(double value)
代码语言:javascript
复制
DoubleToIntFunction doubleToIntFunction = doub -> {
    System.out.println("值为:" + doub);
    return doub.intValue();
};
System.out.println(doubleToIntFunction.applyAsInt(1.2)); // 值为:1.2  1

2.6. ToDoubleBiFunction<T,U>

源码:

代码语言:javascript
复制
@FunctionalInterface
public interface ToDoubleBiFunction<T, U> {

    /**
     * 将此函数应用于给定的参数。
     *
     * @param t 第一个函数参数
     * @param u 第二个函数参数
     * @return 函数结果
     */
    double applyAsDouble(T t, U u);
}

方法:

接口方法

方法描述

double applyAsDouble(T value)

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

方法示例:

  1. double applyAsDouble(T value)
代码语言:javascript
复制
ToDoubleBiFunction<Long, Float> toDoubleBiFunction = (a1, a2) -> a1.doubleValue() + a2.doubleValue();
System.out.println(toDoubleBiFunction.applyAsDouble(11L, 235.5f)); // 246.5

2.7. ToDoubleFunction<T>

源码:

代码语言:javascript
复制
@FunctionalInterface
public interface ToDoubleFunction<T> {

    /**
     * 将此函数应用于给定的参数
     *
     * @param value 函数参数
     * @return 函数结果
     */
    double applyAsDouble(T value);
}

方法:

接口方法

方法描述

double applyAsDouble(T value)

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

方法示例:

  1. double applyAsDouble(T value)
代码语言:javascript
复制
ToDoubleFunction<Float> toDoubleFunction = floa -> floa.doubleValue();
System.out.println(toDoubleFunction.applyAsDouble(12315f)); // 12315.0

3. Consumer 消费者接口

3.1. 分类

序号

接口

描述

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函数的使用方法。

3.2. Consumer<T>

源码:

代码语言:javascript
复制
@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 将会在该函数执行之后执行

方法示例:

  1. void accept(T t, U u)
代码语言:javascript
复制
StringBuilder sb = new StringBuilder("Hello ");
Consumer<StringBuilder> consumer = (str) -> str.append("Jack!");
consumer.accept(sb);
System.out.println(sb.toString());	// Hello Jack!
  1. default Consumer andThen(Consumer<? super T> after)
代码语言:javascript
复制
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!

3.3. BiConsumer<T,U>

源码:

代码语言:javascript
复制
@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 将会在该函数执行之后执行

方法示例:

  1. void accept(T t, U u)
代码语言:javascript
复制
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!
  1. default BiConsumer<T,U> andThen(BiConsumer<? super T,? super U> after)
代码语言:javascript
复制
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!

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 在该函数执行之后执行

方法示例:

  1. void accept(double value)
代码语言:javascript
复制
DoubleConsumer doubleConsumer = System.out::println;
doubleConsumer.accept(1.3); // 1.3
  1. default DoubleConsumer andThen(DoubleConsumer after)
代码语言:javascript
复制
DoubleConsumer doubleConsumer = (a) -> Integer.parseInt(a);
DoubleConsumer doubleConsumer1 = System.out::println;
doubleConsumer.andThen(doubleConsumer1).accept(1.3);  // 1

3.5. ObjDoubleConsumer<T>

源码:

代码语言:javascript
复制
@FunctionalInterface
public interface ObjDoubleConsumer<T> {

    /**
     * 对给定的参数执行此操作
     *
     * @param t 第一个输入参数
     * @param value 第二个输入参数
     */
    void accept(T t, double value);
}

方法:

接口方法

方法描述

void accept(double value)

对给定的参数执行操作

方法示例:

  1. void accept(double value)
代码语言:javascript
复制
ObjDoubleConsumer<String> doubleConsumer = (obj, doub)
	-> System.out.println(obj + doub);
doubleConsumer.accept("金额:", 222.66); // 金额:222.66

后话:

这是第一篇文章,因为内容比较多,所以博主分成了两篇文章发布。第二篇文章里面有介绍Predicate、Supplier、Operator这三个函数式接口的使用。敬请期待~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 函数式接口
    • 1.1. 定义
    • 1.2. 允许存在默认方法
    • 1.3. 允许存在静态方法
    • 1.4. 允许存在Java.Lang.Object类中的 public 方法
  • 2. Function 函数接口
    • 2.1. 分类
    • 2.2. Function<T,R>
    • 2.3. BiFunction<T,U,R>
    • 2.4. DoubleFunction<R>
    • 2.5. DoubleToIntFunction
    • 2.6. ToDoubleBiFunction<T,U>
    • 2.7. ToDoubleFunction<T>
  • 3. Consumer 消费者接口
    • 3.1. 分类
    • 3.2. Consumer<T>
    • 3.3. BiConsumer<T,U>
    • 3.4. DoubleConsumer
    • 3.5. ObjDoubleConsumer<T>
  • 后话:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档