【问题标题】:Consumer with more than one argument in Java 8?具有多个参数的 Java 8 Consumer 在哪里?
【发布时间】:2014-09-06 21:20:35
【问题描述】:

例如在.Net 中,它提供了Action 委托(相当于Java Consumer 功能接口)的几种实现,具有不同数量和类型的参数,我期待Java 8 提供一些指定@ 的方法987654326@ 具有多个不同类型的参数。

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

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

【问题讨论】:

标签: java c# lambda java-8 java-stream


【解决方案1】:

对于 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

【讨论】:

  • 而且,正如它已经提到的,没有其他方法可以在 java8 中定义一个新的函数接口 w/3 或更多参数。
  • 聪明,但我敦促任何考虑这个的人创建一个新的功能界面。
  • @roundar - 对于一次性案例,当然,但如果您需要编写处理这些多消费者案例的通用代码(例如,对于框架),您将很快遇到组合爆炸尝试覆盖所有基地...
  • 可以和java.util.stream.Stream.forEach(Consumer&lt;? super T&gt; action)一起使用吗?
  • @Khinsu 为什么不这样做: IntStream.range(0,10).forEach(elem -> f.apply(1.0).apply(elem).accept("s"));
【解决方案2】:

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

【讨论】:

  • 但是,拥有 MultiConsumer 是个好主意吗?如果我们需要制作 MultiConsumer ,我们的代码是否可能存在设计问题?
  • @MasterJoe2 您可以将任何返回 void 的方法视为消费者方法。它需要多少参数并没有设计缺陷。它可以是 0 也可以是 10。如果您需要该方法,那么您可以为其创建一个消费者功能接口。
【解决方案3】:

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

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

可能有更好的方法可以做到这一点,但我想我会分享对我有用的东西。

【讨论】:

  • 备案:VoidFunction -> 内置Runnable
【解决方案4】:

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

一个对象可以包含任意数量的其他对象。 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));

【讨论】:

    猜你喜欢
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-08
    相关资源
    最近更新 更多