如何在Java 8中组合函数<t,r =“”>和Consumer <r>?

时间:2017-11-27 21:20:44

标签: java java-8 functional-java

为什么我们不能像编写函数一样构成函数和消费者?

Function<Integer, String> a = Object::toString;
Consumer<String> b = x -> System.out.println(x);
Consumer<Integer> composed = a.andThen(b);

这似乎是对现有Function接口的明显即兴创作。是否有任何理由在Java 8中避免使用此功能?

此外,通常的做法是使用函数的扩展实现,如下所示?

interface FunctionImproved<T, R> extends Function<T, R> {
    default Consumer<T> andThen(Consumer<R> consumer) {
        return x -> consumer.accept(apply(x));
    }
}

2 个答案:

答案 0 :(得分:2)

andThen个实例上的Function<A0, A1>方法需要Function<A1, A2>,而不是Consumer<A1>

a.andThen(string -> {
    b.accept(string);
    return string;
});

由于我们的消费者&#34;它有副作用。 (实际上,它是Function<A1, A1>)将从之前的Function<Integer, String> a函数返回一个被忽略的值。这不是我们想要的。

撰写Function<A0, A1>Consumer<A1>

的方法有所不同
Consumer<Integer> c = i -> b.accept(a.apply(i));

可以推广到实用方法:

<A0, A1> Consumer<A0> functionAndThenConsumer(Function<A0, A1> f, Consumer<A1> c) {
    return i -> c.accept(f.apply(i));
}
  

使用Function的扩展实现是否是一种常见做法?

有两种选择:

  1. 使用静态方法在功能接口之间进行一些转换(就像我一样)。

  2. 使用默认方法扩展这些标准功能接口(就像您一样)。只需选择一个正确有意义的名称,而不是FunctionImproved

答案 1 :(得分:1)

FunctionConsumer为两位不同的主人服务(在某种意义上)。

  • 一个函数接受一个(或BiFunction个)类型并生成第三个类型,可以是第一个或第二个类型。
  • 消费者接受一个(或BiConsumer个)类型,并生成 no 输出。

两个案例中,应该执行离散操作,这样可以更轻松地推理操作&# 39; s线程安全。

看起来就像你正在尝试将一种类型的简单映射到另一种类型(String to Integer),然后在其上调用一个操作。如果您的元素位于Stream,则可以写为:

elements.map(Objects::toString).forEach(System.out::println);

...如果它在集合或IntStream中,您可以改为使用它:

elements.forEach(System.out::println);

最终,您尝试的可能是寻找问题的解决方案。一旦你对功能和消费者实际扮演的角色更加清楚,那么对上述作品的尝试就变得不那么必要了。