【问题标题】:Applying functions of various types to a value将各种类型的函数应用于值
【发布时间】:2021-04-03 22:43:33
【问题描述】:

假设我有一个方法将多个函数应用于一个值

示例用法:

String value = "a string with numb3r5";
Function<String, List<String>> fn1 = ...
Function<List<String>, String> fn2 = ...
Function<String, List<Integer>> fn3 = ...

InputConverter<String> converter = new InputConverter<>(value);
List<Integer> ints = converter.convertBy(fn1, fn2, fn3);

是否可以使其应用具有各种输入和返回值的多个功能?

我尝试过使用通配符,但这不起作用。

public class InputConverter<T> {
    private final T src;

    public InputConverter(T src) {
        this.src = src;
    }

    public <R> R convertBy(Function<?, ?>... functions) {
        R value = (R) src;

        for (Function<?, ?> function : functions)
            value = (R) function.apply(value);
                                       ^^^^^
        return value;
    }
}

【问题讨论】:

  • 使用StreamOptional。或者从他们的设计中汲取灵感。

标签: java generics functional-programming bounded-wildcard


【解决方案1】:

您可以在Function 上使用链,如下所示

Function<String, List<Integer>> functionChain = fn1.andThen(fn2).andThen(fn3);

您可以使用原始类型实现几乎相同的目标

@SuppressWarnings({"unchecked", "rawtypes"})
public <R> R convertBy(Function... functions) {
    Function functionsChain = Function.identity();

    for (Function function : functions) {
        functionsChain = functionsChain.andThen(function);
    }

    return (R) functionsChain.apply(src);
}

否则,我看到的唯一其他方法是使用与 OptionalStream 相同的模式,就像 cmets 中建议的那样

List<Integer> fileInputStreams = converter.convertBy(fn1)
        .convertBy(fn2)
        .convertBy(fn3)
        .get();

// with this implementation

public static class InputConverter<T> {
    private final T src;

    public InputConverter(T src) {
        this.src = src;
    }

    public <R> InputConverter<R> convertBy(Function<T, R> function) {
        return new InputConverter<>(function.apply(src));
    }

    public T get() {
        return src;
    }
}

【讨论】:

  • 不使用原始类型是否可以实现?
  • 我在发布这个问题之前找到了一个非常相似的答案:stackoverflow.com/a/44521687/10430194 解决方案非常优雅。不幸的是,这只适用于返回类型一致的情况。
  • @Bart 我已经添加了一个可能合适的解决方案,我不确定是否可以在这里使用完整的泛型,因为要推断的类型是动态的,而 Java 并不是完美的这种灵活性的语言
  • 这是一个非常彻底的答案,我的朋友。我将您的答案与功能性方法结合起来,并返回类似 return (R) Arrays.stream(functions).reduce(Function.identity(), Function::andThen).apply(src); 的内容。我将您的标记为最佳答案。谢谢!
猜你喜欢
  • 2012-08-31
  • 2016-06-20
  • 1970-01-01
  • 2014-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多