将消费者转换为功能

时间:2016-04-03 22:52:07

标签: java java-8 java-stream

t -> { // do something to t return t; } 接口的许多lambdas采用

形式
static <T> Function<T, T> consumeThenReturn(Consumer<T> consumer) {
    return t -> {
        consumer.accept(t);
        return t;
    };
}

我经常这样做,因此我为此编写了一个方法。

IntStream.rangeClosed('A', 'Z')
         .mapToObj(a -> (char) a)
         .collect(Collectors.collectingAndThen(Collectors.toList(), consumeThenReturn(Collections::shuffle)))
         .forEach(System.out::print); 

这使我能够做到这样的好事:

fa_IR.UTF-8

有没有其他方法可以在不依赖我自己的方法的情况下进行这样的转换?我错过的新API中有什么东西会让我的方法变得多余吗?

2 个答案:

答案 0 :(得分:6)

有许多可能有用的方法可以添加到FunctionConsumerSupplier接口。您举了一个很好的示例(将Consumer转换为Function),但还有许多其他潜在的转化或实用程序可以添加。例如,使用Function作为Consumer(通过忽略返回值)或作为Supplier(通过提供输入值)。或者通过提供任一值将BiFunction转换为Function。当然,所有这些都可以在代码中手动完成,或者如您所示通过实用程序功能提供,但在API中具有标准化机制可能是有价值的,如许多其他语言中所存在的那样。

这是我的猜测,但我猜这反映了语言设计者希望尽可能保持API清洁的愿望。然而,我对这种语言提供的非常丰富的Comparator实用程序的对比(作为一个例子)很感兴趣,这些实用程序可以反转命令,按照几个标准进行比较,处理空值等。这些也很容易被留给用户,但由API提供。我很想知道其中一位语言设计师为什么这些接口的方法看起来如此不一致。

答案 1 :(得分:1)

我认为Apache commons集合4.x有你正在寻找的东西。它与FunctionConsumer的等价物分别为TransformerClosure,它提供了使用ClosureTransformer

组合它们的方法

通过调用SAM的SAM并将其分配给另一个来转换等效的函数类型是微不足道的。总而言之,您最终可以用这种方式获得Java 8 Function

Consumer<String> c = System.out::println;
Function<String,String> f = ClosureTransformer.closureTransformer(c::accept)::transform;

c::accept将Java 8 Consumer转换为等效的Apache Commons 4 Closure,最终::transform将Apache Commons 4 Transformer转换为等效的Java 8 Function