Function<T, R> 中 apply,compose, andThen 方法总结

一,背景介绍

在正常使用中,我们平时定义方法都是类似这样,

复制代码
    public static String fixStringLength(String numberArg){
        int length = numberArg.length();
        switch (length){
            case 1:
                return "00"+numberArg;
            default:
                return "fix" + numberArg;
        }
    }

然后通过在其他代码中引用该方法来使用,例如,

复制代码
    public static void main(String[] args) {
        fixStringLength("486");
    }

Stream 中的 Function 实际上解决了一个简单的问题,那就是我们在实际书写代码的时候,一个方法一般只能作为代码中的某一行函数,用于处理里面的数值,但是并不能将一个方法作为一个参数,将方法以参数的形式,将方法传递到下一个方法中继续使用。

源码以及使用示例

复制代码
@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);

    /**
     * Returns a composed function that first applies the {@code before}
     * function to its input, and then applies this function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of input to the {@code before} function, and to the
     *           composed function
     * @param before the function to apply before this function is applied
     * @return a composed function that first applies the {@code before}
     * function and then applies this function
     * @throws NullPointerException if before is null
     *
     * @see #andThen(Function)
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     *
     * @see #compose(Function)
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Function 是作为一种方法接口,两个泛型 T, R 在这里分别指代的是方法的入参以及返回值的泛型。

  1. apply

    复制代码
     /**
      * Applies this function to the given argument.
      *
      * @param t the function argument
      * @return the function result
      */
     R apply(T t);

apply 的作用为执行当前方法函数,t 为入参,R 为返回值类型

示例:

复制代码
    public static void main(String[] args) {
// 定义函数 但没有创建实际方法而是类似于将方法(function1)作为一个变量,对以此来直接在行内引用方法对象,达到和方法一样的效果
        Function<Integer, String> function1 = item -> {
            item *=  100;
            return item + "";
        };

        String apply = function1.apply(13);
        System.out.println("apply = " + apply);
	}

结果如下:

  1. compose

    复制代码
     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 中的apply 方法,再将计算的结果作为原有方法的 apply 入参

示例:

复制代码
    public static void main(String[] args) {

        // 定义函数 但没有创建实际方法而是类似于将方法 这里的 function1 作为一个变量,对象  以此来直接在行内引用方法对象 达到和方法一样的效果
        Function<Integer, String> function1 = item -> {
            item *=  100;
            return item + "";
        };

        String apply = function1.apply(13);
        System.out.println("apply = " + apply);

        // 定义的第二个方法函数
        Function<Integer, Integer> function2 = item -> item + 10;
        // 先将 13 作为function2的入参 然后将结果作为function1的入参继续计算
        String apply2 = function1.compose(function2).apply(13);
        System.out.println("apply2 = " + apply2);
    }
  1. andThen

    复制代码
     default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
         Objects.requireNonNull(after);
         return (T t) -> after.apply(apply(t));
     }

andThen 与compose 类似,但是方向相反

示例:

复制代码
    public static void main(String[] args) {

        // 定义函数 但没有创建实际方法而是类似于将方法 这里的 function1 作为一个变量,对象  以此来直接在行内引用方法对象 达到和方法一样的效果
        Function<Integer, String> function1 = item -> {
            item *=  100;
            return item + "";
        };

        String apply = function1.apply(13);
        System.out.println("apply = " + apply);

        // 定义的第二个方法函数
        Function<Integer, Integer> function2 = item -> item + 10;
        // 先将 13 作为function2的入参 然后将结果作为function1的入参继续计算
        String apply2 = function1.compose(function2).apply(13);
        System.out.println("apply2 = " + apply2);

        // 定义的第三个方法函数
        Function<String, Integer> function3 = item -> Integer.valueOf(item) + 31;
        // 先将 13 作为function1的入参 然后将结果作为function3的入参继续计算
        Integer apply3 = function1.andThen(function3).apply(13);
        System.out.println("apply3 = " + apply3);

        // 使用其他已定义的方法 示例
        String apply4 = function1.andThen(App::fixStringLength).apply(13);
        System.out.println("apply4 = " + apply4);

    }

结果如下:

相关推荐
JAVA面经实录91724 分钟前
企业级java+LangChain4j-RAG系统 限流熔断降级
java·开发语言·分布式·langchain
Drug29 分钟前
Struts2 从入门到放弃?不,这些核心知识你依然需要掌握
java
Slow菜鸟35 分钟前
Codex CLI 教程(五)| AI 驱动项目从零到一:面向 Java 全栈工程师打造个人 ECC(V2版)
java·开发语言·人工智能
月落归舟44 分钟前
java基础之拷贝、单例
java·单例·拷贝
鬼蛟1 小时前
什么是 Git
java
y = xⁿ1 小时前
Redis八股学习日记:布隆过滤器
数据库·redis·学习
直奔標竿1 小时前
SpringAI + RAG + MCP + Agent 零基础全栈实战(完结篇)| 27课完整汇总,Java开发者AI转型必看
java·开发语言·人工智能·spring boot·后端·spring
云烟成雨TD1 小时前
Spring AI 1.x 系列【31】向量数据库:进阶使用指南
java·人工智能·spring
万邦科技Lafite2 小时前
京东开放API接口:item_get返回参数指南
java·前端·javascript·api·电商开放平台
曹牧2 小时前
Java:处理 HTTP 请求的 Content-Type
java·开发语言