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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24704791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 14:17:33  来源:igfitidea点击:

Returning a value from a method within a lambda expression

javalambdajava-8

提问by Rogue

I'm trying to figure out how to return a method value from a lambda expression:

我试图弄清楚如何从 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;
}

However, it seems that using the returnkeyword in the lambda expression will explicitly return to the lambda function itself. Is there some type of way to break or force a return for the entire method?

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

采纳答案by Jon Skeet

Is there some type of way to break or force a return for the entire method?

是否有某种类型的方法可以中断或强制返回整个方法?

No. At least, not unless you throw an exception.

不。至少,除非你抛出异常。

Basically, that's not what forEachis meant for. You could write a method which accepted a function which would return nullfor "keep going" and non-null for "stop, and make this the result"... but that method isn'tforEach.

基本上,这不是forEach目的。您可以编写一个方法,该方法接受一个函数,该函数将返回null“继续前进”和非空“停止,并使其成为结果”......但该方法不是forEach

The fact that you're using a lambda expression is really incidental here. Imagine you were just calling forEachand passing in some argument - wouldn't it be reallyweird if that call made your findMissingNumbermethod return (without an exception), without the findMissingNumbermethod itself having the return statement?

您使用 lambda 表达式的事实在这里真的很偶然。想象一下,您只是在调用forEach并传入一些参数 -如果该调用使您的方法返回(没有异常),而方法本身没有 return 语句,这会不会奇怪?findMissingNumberfindMissingNumber

回答by Stuart Marks

(Is this an instance of the XY problem?)

(这是XY 问题的一个实例吗?)

The question is about how to return from a lambda inside a forEach. Jon Skeetprovided some useful information about findFirstand also cautioned about side effects in a lambda run in parallel -- both excellent points.

问题是如何从forEach. Jon Skeet提供了一些关于findFirstlambda 并行运行中的副作用的有用信息,也警告了这些副作用——这两点都很出色。

But regarding the original question, I'm still thinking: what problem are you trying to solve?

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

The method name findMissingNumberin the example is suggestive. The method takes a collection of numbers as a parameter and iterates over it while incrementing a counter. It returns when it finds a mismatch, or it returns -1 if there is no mismatch. Since the counter is incremented once as each value in the intscollection is processed, it seems like that collection is expected to be in order, unless a number is missing.

findMissingNumber示例中的方法名称具有启发性。该方法将一组数字作为参数,并在递增计数器的同时对其进行迭代。它在发现不匹配时返回,如果没有不匹配则返回 -1。由于在ints处理集合中的每个值时计数器都会递增一次,因此该集合似乎是有序的,除非缺少一个数字。

If so, the parameter ought to be a Listinstead of a Collection. (Making a big assumption here.) Under this assumption, one could rewrite the code using lambdas as streams like so:

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

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

Instead of incrementing a counter, we use IntStream.rangeto generate the values expected to be in the list. We then rely on random access to the list to getvalues from their expected positions in the list. We filter for the mismatches and return the first one, if any. This avoids mutation and so should run correctly in parallel. (Note that this doesn't parallelize well if the list isn't random-access, though.)

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

The return value is an OptionalIntwhich is emptyif no mismatch was found. This is more explicit than using a sentinel value like -1to indicate the "not found" condition.

如果未发现不匹配OptionalInt,则返回值为。这比使用标记值更明确,例如-1指示“未找到”条件。