Java 8 中消费者有多个参数?

问题描述 投票:0回答:5

例如在 .Net 中,它提供了多种具有不同数量和类型参数的

Action
委托(相当于 Java
Consumer
函数式接口)的实现,我期望 Java 8 提供某种指定
Consumer
的方法有多个不同类型的参数。

我知道在Java中我们不能定义具有相同名称的不同类型,只是泛型类型参数不同,但是会有很好的流畅替代方案来提供多参数

Consumer

有没有什么简单的方法可以做到,不需要定义新的功能接口?

lambda java-8 java-stream
5个回答
56
投票

对于 3 个及更多参数,您可以对最后一个消费者使用 curried(http://en.wikipedia.org/wiki/Currying) 函数:

Function<Double, Function<Integer, Consumer<String>>> f = d -> i -> s -> {
            System.out.println("" + d+ ";" + i+ ";" + s); 
        };
f.apply(1.0).apply(2).accept("s");

输出为:

1.0;2;s

用一个参数的函数来表达任意数量参数的函数就足够了: https://en.wikipedia.org/wiki/Currying#Lambda_calculi


43
投票

默认情况下,您只能使用

java.util.function.Consumer
java.util.function.BiConsumer
。它们对于当前的 java 流 API 来说已经足够了。但是您可以创建自己的函数接口,该接口将接收任意数量的参数,并在您自己的自定义 API 中使用它。


11
投票

为自己定义函数式接口非常容易。在我目前正在从事的项目中,我发现有几次将方法作为参数传递可以使我的代码保持良好和干燥。以下是我定义的一些功能接口:

@FunctionalInterface
public interface CheckedVoidFunction {
    void apply() throws Exception;
}

@FunctionalInterface
public interface VoidFunction {
    void apply();
}

@FunctionalInterface
public interface SetCategoryMethod {
    void accept(ObservableList<IRegionWithText> list, Document document, String pattern);
}

以下是接受此类参数的方法:

private void loadAnnotations(String annotationType, VoidFunction afterLoadFunction, List<Path> documentPaths) {

这是我用不同的方法作为参数调用这些方法的地方:

loadAnnotations(DocumentReader.REDACTION_ANNOTATION_TYPE, this::afterLoadRedactions, documentPaths);
loadAnnotations(DocumentReader.HIGHLIGHT_ANNOTATION_TYPE, this::afterLoadHighlights, documentPaths);

可能有更好的方法来做到这一点,但我想我应该分享对我有用的方法。


3
投票

有没有什么简单的方法可以做到,不需要定义新的功能接口?

一个对象可以包含任意数量的其他对象。 Streams API 旨在一次仅传输一个对象,如果您需要更多对象,您可以将它们包装在一个包含所有对象的对象中。

例如

Map<String, Long> map = new HashMap<>();
// each entry has a key and a value as Map.Entry<String, Long>
Map<Long, String> revMap = map.entrySet().stream()
            .collect(groupingBy(Entry::getValue(), HashMap::new, Entry::getKey));

0
投票

您可以简单地使用列表:

Consumer<List> myFunction = (myListOfParameter) -> {
   myListOfParameter.forEach(System.out::println);
};

myFunction.accept(Arrays.asList(
        "firstAString",
        true,
        1));
© www.soinside.com 2019 - 2024. All rights reserved.