我试图弄清楚如何从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函数本身。是否有某种方法可以打破或强制退出整个方法?
答案 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
这样的标记值来表示“未找到”条件更明确。