从lambda表达式中的方法返回值

时间:2014-07-11 19:06:28

标签: java lambda java-8

我试图弄清楚如何从lambda表达式返回一个方法值:

public int findMissingNumber(Collection<Integer> ints) {
    Single<Integer> start = new Single<>(1);
    ints.stream().mapToInt(Integer::valueOf).parallel().forEach(i -> {
        if (i != start.setValue(start.getValue() + 1)) {
            //return here
        }
    });
    return -1;
}

但是,似乎在lambda表达式中使用return关键字将显式返回lambda函数本身。是否有某种方法可以打破或强制退出整个方法?

2 个答案:

答案 0 :(得分:19)

  

是否有某种方法可以打破或强制返回整个方法?

没有。至少,除非你抛出异常。

基本上,这不是forEach的意思。您可以编写一个方法,该方法接受一个函数,该函数将返回null用于&#34;继续&#34;对于&#34;停止非空,并将其作为结果&#34; ...但该方法不是 forEach

你使用lambda表达式的事实在这里是偶然的。想象一下,你只是在调用forEach并传递一些参数 - 如果该调用使你的findMissingNumber方法返回(没有例外),那么真的很奇怪,没有findMissingNumber方法本身有return语句?

答案 1 :(得分:12)

(这是XY problem的实例吗?)

问题是关于如何从forEach内的lambda返回。 Jon Skeet提供了一些有关findFirst的有用信息,同时也警告了lambda并行中的副作用 - 这两点都非常好。

但对于最初的问题,我仍然在想:你想解决什么问题?

示例中的方法名称findMissingNumber是暗示性的。该方法将一组数字作为参数,并在递增计数器时对其进行迭代。它在找到不匹配时返回,或者如果没有不匹配则返回-1。由于计数器在处理ints集合中的每个值时递增一次,因此除非缺少数字,否则看起来该集合应该是有序的。

如果是这样,参数应该是List而不是Collection。 (在这里做一个很大的假设。)在这个假设下,可以使用lambdas将代码重写为如下所示的流:

static OptionalInt findMissingNumber(List<Integer> ints) {
    return
        IntStream.rangeClosed(1, ints.size())
            .filter(i -> i != ints.get(i-1))
            .findFirst();
}

我们使用IntStream.range生成预期在列表中的值,而不是递增计数器。然后,我们依赖于从列表中的预期位置随机访问列表中的get值。我们过滤不匹配并返回第一个,如果有的话。这可以避免突变,因此应该并行正确运行。 (请注意,如果列表不是随机访问,则不会很好地并行化。)

如果未找到不匹配,则返回值为OptionalInt 为空。这比使用像-1这样的标记值来表示“未找到”条件更明确。