【问题标题】:Java Function with three parameters callable from methods具有三个可从方法调用的参数的 Java 函数
【发布时间】:2019-07-05 17:19:10
【问题描述】:

我有这个方法,它调用多个 API 并聚合所有结果并在 Map 中返回它们,其中每组结果都与目标 API 匹配,以便它们可以在服务中正确分组和显示。

public AggregateResults search(QueryParams params) {
    Stream<APITarget> targets = params.getTargets().parallelStream();

    Function<APITarget, APIResults> func = (APITarget target) -> {
        if (params.length() >= MIN_LENGTH) {
           switch (target) {
               case api1:
                    return searchAPI1(params);
               case api2:
                   return searchAPI2(params);
               .
               .
               case apin:
                    return searchAPIn(params);
            }
        }
        return new APIResults.Builder().build();
    };

    Map<APITarget, APIResults> results = targets.collect(Collectors.toMap(t -> t, func));
    return AggregateResults;
}

我现在必须重构这段代码,例如 API 1 - 3 可以在一个函数中调用,然后 API 4 - N 可以从另一个函数中调用。这些函数将从不同的方法调用,因此我需要将此函数移出此方法,然后将 QueryParams 对象作为另一个参数传递给该函数,但随后我遇到了函数无法接受的问题一个参数。 例如

Function<APITarget, APIResults> exampleFunc = (APITarget target, QueryParams params) -> {
    if (params.length() >= MIN_LENGTH) {
        switch (target) {
            case api1:
                return searchAPI1(params);
            case api2:
                return searchAPI2(params);            
        }
    }
    return new APIResults.Builder().build();
};

我在这里看到过类似的东西:Can a java lambda have more than 1 parameter? 但是 BiFunctions 的示例仅显示它们被用作 lambdas,因此在被外部方法调用时不起作用,据我所知。 此外,当它谈到创建新的 FunctionalInterface 时,我不确定要在我所需的函数中使用新接口究竟需要什么。

任何想法都会很棒。

【问题讨论】:

  • BiFunction&lt;APITarget, QueryParams, APIResults&gt; 有什么问题? “...仅显示它们被用作 lambdas,因此在被外部方法调用时将不起作用” - 我不明白你问题的那一部分。
  • 这个例子是一个 lambda BiFunction&lt;String, String, String&gt; function1 = (s1, s2) -&gt; { String s3 = s1 + s2; return s3; }; 我需要能够在类中定义函数,然后从两个不同的方法中调用它,比如 Map&lt;APITarget, APIResults&gt; results = targets.collect(Collectors.toMap(t -&gt; t, func(t,params)));

标签: java function lambda java-stream


【解决方案1】:

修改以反映示例

首先,定义一些必需的BiFunction


  BiFunction<Integer, int[], Integer> func = (a, b) ->
      {
         for (int i = 0; i < b.length; i++) {
            a *= b[i];
         }
         return Integer.valueOf(a);
      };


现在定义一些数据。

      //Stream source
      int[] data = { 10, 20, 30
      };
      // parameter source
      int[] params = { 3, 5, 11
      };
      Convert data to stream
      IntStream targets = Arrays.stream(data);

现在应用映射函数。


     Map<Integer, Integer> results = targets.boxed().collect(
            Collectors.toMap(t -> t, t -> func.apply(t, params)));
      System.out.println(results);

上面采用stream 并使用充当keys 的数据创建一个映射,然后采用这些相同的键并将它们应用于参数列表的功能。这就是地图的价值。

您可能需要使用mapToObjmap 代替上面的boxed() 方法,具体取决于初始流类型。

【讨论】:

  • 是的,但是在定义函数后没有直接执行 lambda,我在上面的 cmets 中添加了一个示例
  • @Anto 我根据您的示例修改了我的答案。仍然不确定这是否是您想要的。
  • 感谢@WJS!我以为我已经尝试过了,但我显然有问题,因为它要么抱怨参数进入函数,要么抱怨“预期方法调用”
【解决方案2】:

函数式接口(简单来说)是具有一种方法的接口。

您希望使用 @FunctionalInterface 注释接口以记录其用途,并确保没有人意外添加其他方法。

方法的名称并不重要,但当然应该适合它应该做的事情。

所以,如果您需要一个具有 3 个参数的函数,请创建您自己的函数式接口。您可以使用泛型类型参数使其具体化或通用化。

@FunctionalInterface
interface TripleString {
    String doStringOp(String a, String b, String c);
}

@FunctionalInterface
interface TriFunction<T, U, V, R> {
    R apply(T t, U u, V v);
}

【讨论】:

  • 我认为我的主要问题是,在像上面那样定义一个 FuinctionalInterface 然后像 TriFunction&lt;SearchTarget, QueryParams, SearchResults,SearchResults&gt; trifunc = (SearchTarget target, QueryParams params, SearchResults results) -&gt; {... return apiresults }; 那样定义我的函数或使用 BiFunction 之后,我无法弄清楚如何在地图中使用它,如 @987654325 @Maybe 函数只能在 lambdas 中使用,如下面的答案
猜你喜欢
  • 2019-10-22
  • 1970-01-01
  • 2011-12-24
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多