为啥我不能用相同的参数类型组合两个不同的函数?

Posted

技术标签:

【中文标题】为啥我不能用相同的参数类型组合两个不同的函数?【英文标题】:Why can't I compose two different functions with identical parameter types?为什么我不能用相同的参数类型组合两个不同的函数? 【发布时间】:2022-01-22 05:29:43 【问题描述】:

我有以下代码:

        Function<String,Integer> f1=s->Integer.valueOf(s)+1;
        Function<String,Integer> f2=s->Integer.valueOf(s)*2;
        Function<String,Integer> f3=f1.compose(f2);

这是我得到的错误:

method compose in interface Function<T,R> cannot be applied to given types;

这段代码有什么问题?

然后我查看了文档中的compose()

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) 
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
    

我无法完全理解它。谁能给我解释一下可以组合的函数的参数之间的关系?

【问题讨论】:

【参考方案1】:

组合两个函数意味着一个函数的结果将作为另一个函数的输入。因此,如果您有两个函数具有相同的输入类型和相同的输出类型,但输入和输出类型不同,则它们不能按任何顺序组合。

在您的特定情况下,您请求的组合函数将f1() 应用于f2() 的结果,但f2() 的结果是Integer,而f1() 需要@ 类型的输入987654326@。解决该问题的一种方法是修改f1(),使其在Integers 上运行:

        Function<Integer, Integer> f1 = i -> i + 1;
        Function<String, Integer> f2 = s -> Integer.valueOf(s) * 2;
        Function<String, Integer> f3 = f1.compose(f2);

如果您无法修改f1(),那么您可以在您的合成链中插入一个返回String 的中间转换:

        Function<String, Integer> f1=s->Integer.valueOf(s)+1;
        Function<String, Integer> f2 = s -> Integer.valueOf(s) * 2;
        Function<String, Integer> f3 = f1.compose(f2.andThen(Integer::toString));

当然,所有这些来回转换到String 的成本都很高。

【讨论】:

【参考方案2】:

函数组成“链”函数,函数本身具有结果类型。当然,您的具有不同输入类型和输出类型的函数不能在同一函数中“重用”。将 compose 视为按顺序执行功能:第一步:f2 中的字符串,输出为整数。然后 f1 中的 f2 的输出具有作为输入的字符串,而不是整数。因此,您的功能 compose 将不起作用。如果第一个函数的输出可以用作第二个函数的输入,则只能链接一个函数:

        Function<Integer, Integer> f1 = i -> i + 1;
        Function<String, Integer> f2 = s -> Integer.valueOf(s) * 2;
        Function<String, Integer> f3 = f1.compose(f2);

【讨论】:

You can only chain a function if the output of the first function can be used as input of the second function 这一行让一切都清楚了!

以上是关于为啥我不能用相同的参数类型组合两个不同的函数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能用相同的签名声明两个方法,即使它们的返回类型不同? [复制]

是否可以创建一个函数而不是两个具有相同目的但参数类型不同的函数? (我可以删除重复的代码吗?)[重复]

为啥我不能有两个带有 ArrayList 参数的方法?

为啥我不能编写与 Box::new 相同类型的函数?

动手动脑

如何将不同类型的结构体作为一个函数的参数?