将消费者转化为职能


问题内容

Function接口的许多lambda都采用以下形式

t -> {
    // do something to t
    return t;
}

我经常这样做,以至于我为此写了一个方法。

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);

是否有另一种方法可以在不依赖我自己的方法的情况下进行这样的转换?我错过了新API中的任何东西,这些东西使我的方法变得多余了吗?


问题答案:

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

这只是我的猜测,但我想这可能反映了语言设计师希望将API保持尽可能干净的愿望。但是,我对Comparator这种语言提供的非常丰富的实用程序(例如,反向订单,按多个条件进行比较,处理空值等)的对比感到很感兴趣(这些示例)。这些也很容易留给用户,但是由API提供。我很想听听一位语言设计师的意见,为什么这些界面的方法看起来如此不一致。