在java中从lambda forEach()返回
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23407014/
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
Return from lambda forEach() in java
提问by samutamm
I am trying to change some for-each loops to lambda forEach()
-methods to discover the possibilities of lambda expressions. The following seems to be possible:
我试图将一些 for-each 循环更改为 lambda forEach()
-methods 以发现 lambda 表达式的可能性。以下似乎是可能的:
ArrayList<Player> playersOfTeam = new ArrayList<Player>();
for (Player player : players) {
if (player.getTeam().equals(teamName)) {
playersOfTeam.add(player);
}
}
With lambda forEach()
与拉姆达 forEach()
players.forEach(player->{if (player.getTeam().equals(teamName)) {playersOfTeam.add(player);}});
But the next one doesn't work:
但下一个不起作用:
for (Player player : players) {
if (player.getName().contains(name)) {
return player;
}
}
with lambda
与 lambda
players.forEach(player->{if (player.getName().contains(name)) {return player;}});
Is there something wrong in the syntax of the last line or is it impossible to return from forEach()
method?
最后一行的语法有问题还是无法从forEach()
方法返回?
采纳答案by Ian Roberts
The return
there is returning from the lambda expression rather than from the containing method. Instead of forEach
you need to filter
the stream:
在return
那里,从λ表达式,而不是从包含方法返回。而不是forEach
你需要filter
流:
players.stream().filter(player -> player.getName().contains(name))
.findFirst().orElse(null);
Here filter
restricts the stream to those items that match the predicate, and findFirst
then returns an Optional
with the first matching entry.
这里filter
将流限制为匹配谓词的那些项目,findFirst
然后返回Optional
带有第一个匹配条目的 。
This looks less efficient than the for-loop approach, but in fact findFirst()
can short-circuit - it doesn't generate the entire filtered stream and then extract one element from it, rather it filters only as many elements as it needs to in order to find the first matching one. You could also use findAny()
instead of findFirst()
if you don't necessarily care about getting the firstmatching player from the (ordered) stream but simply any matching item. This allows for better efficiency when there's parallelism involved.
这看起来比 for 循环方法效率低,但实际上findFirst()
可以短路 - 它不会生成整个过滤流,然后从中提取一个元素,而是只过滤尽可能多的元素,以便找到第一个匹配的。如果您不一定关心从(有序)流中获取第一个匹配的播放器,而只关心任何匹配的项目,您也可以使用findAny()
代替。当涉及并行性时,这可以提高效率。findFirst()
回答by skiwi
I suggest you to first try to understand Java 8 in the whole picture, most importantly in your case it will be streams, lambdas and method references.
我建议您首先尝试从整体上理解 Java 8,最重要的是在您的情况下它将是流、lambda 和方法引用。
You should neverconvert existing code to Java 8 code on a line-by-line basis, you should extract features and convert those.
您永远不应该将现有代码逐行转换为 Java 8 代码,您应该提取特征并转换它们。
What I identified in your first case is the following:
我在你的第一个案例中确定的内容如下:
- You want to add elements of an input structure to an output list if they match some predicate.
- 如果输入结构的元素与某个谓词匹配,您希望将它们添加到输出列表中。
Let's see how we do that, we can do it with the following:
让我们看看我们如何做到这一点,我们可以通过以下方式做到这一点:
List<Player> playersOfTeam = players.stream()
.filter(player -> player.getTeam().equals(teamName))
.collect(Collectors.toList());
What you do here is:
你在这里做的是:
- Turn your input structure into a stream (I am assuming here that it is of type
Collection<Player>
, now you have aStream<Player>
. - Filter out all unwanted elements with a
Predicate<Player>
, mapping every player to the boolean true if it is wished to be kept. - Collect the resulting elements in a list, via a
Collector
, here we can use one of the standard library collectors, which isCollectors.toList()
.
- 将您的输入结构转换为流(我在这里假设它的类型是
Collection<Player>
,现在您有一个Stream<Player>
. - 用 a 过滤掉所有不需要的元素,
Predicate<Player>
如果希望保留,则将每个玩家映射到布尔值 true。 - 通过 a 收集列表中的结果元素
Collector
,这里我们可以使用标准库收集器之一,即Collectors.toList()
.
This also incorporates two other points:
这还包括另外两点:
- Code against interfaces, so code against
List<E>
overArrayList<E>
. - Use diamond inference for the type parameter in
new ArrayList<>()
, you are using Java 8 after all.
- 针对接口进行编码,因此针对
List<E>
over 进行编码ArrayList<E>
。 - 对中的类型参数使用菱形推断,
new ArrayList<>()
毕竟您使用的是 Java 8。
Now onto your second point:
现在进入你的第二点:
You again want to convert something of legacy Java to Java 8 without looking at the bigger picture. This part has already been answered by @IanRoberts, though I think that you need to do players.stream().filter(...)...
over what he suggested.
您再次希望将遗留 Java 的某些内容转换为 Java 8,而无需着眼于大局。这部分已经由@IanRoberts回答,但我认为你需要按照players.stream().filter(...)...
他的建议做。
回答by user5495300
This what helped me:
这对我有帮助:
List<RepositoryFile> fileList = response.getRepositoryFileList();
RepositoryFile file1 = fileList.stream().filter(f -> f.getName().contains("my-file.txt")).findFirst().orElse(null);
Taken from Java 8 Finding Specific Element in List with Lambda
回答by Sriram
If you want to return a boolean value, then you can use something like this (much faster than filter):
如果你想返回一个布尔值,那么你可以使用这样的东西(比过滤器快得多):
players.stream().anyMatch(player -> player.getName().contains(name));
回答by nabster
You can also throw an exception:
您还可以抛出异常:
Note:
笔记:
For the sake of readability each step of stream should be listed in new line.
为了可读性起见,流的每个步骤都应在新行中列出。
players.stream()
.filter(player -> player.getName().contains(name))
.findFirst()
.orElseThrow(MyCustomRuntimeException::new);
if your logic is loosely "exception driven" such as there is one place in your code that catches all exceptions and decides what to do next. Only use exception driven development when you can avoid littering your code base with multiples try-catch
and throwing these exceptions are for veryspecial cases that you expect them and can be handled properly.)
如果您的逻辑是松散的“异常驱动”,例如您的代码中有一个地方可以捕获所有异常并决定下一步做什么。仅当您可以避免使用倍数乱扔代码库try-catch
并且抛出这些异常用于您期望它们并且可以正确处理的非常特殊的情况时,才使用异常驱动开发。)