[英]Using Streams to replace loops
I have the following code:我有以下代码:
boolean found = false;
for (Commit commit : commits.values()) {
if (commit.getLogMessage().compareTo(commitMessageToSearch) == 0) {
System.out.println(commit.getSha());
found = true;
}
}
if (!found) {
System.out.println("aksdhlkasj");
}
You can use Stream#filter
along with Stream#findFirst
.您可以将Stream#filter
与Stream#findFirst
一起使用。
System.out.println(commits.values().stream()
.filter(commit -> commit.getLogMessage().compareTo(commitMessageToSearch) == 0)
.findFirst().map(Commit::getSha).orElse("aksdhlkasj"));
Just replacing your logic with stream functionality, using lambda expression只需使用 lambda 表达式用 stream 功能替换您的逻辑
boolean found = false;
commits.values().stream().filter(c ->
c.getLogMessage().compareTo(commitMessageToSearch) == 0).forEach(c -> {
System.out.println(c.getSha());
found = true;
});
if (!found) {
System.out.println("aksdhlkasj");
}
As there is a "state" that needs to be checked outside the loop, a stream-based solution using Stream::forEach
would set found
value outside the stream and therefore is not pure but it prints all filtered SHA codes as the for-loop
version:由于需要在循环外检查“状态”,因此使用Stream::forEach
的基于流的解决方案将在 stream 之外设置found
的值,因此不是纯的,但它会将所有过滤的 SHA 代码打印为for-loop
版本:
AtomicBoolean found = new AtomicBoolean(); // effectively final container boolean
commits.values().stream()
.filter(commit -> commit.getLogMessage().compareTo(commitMessageToSearch) == 0)
.map(Commit::getSha)
.forEach(sha -> {
found.set(true);
System.out.println(sha);
});
if (!found.get()) {
System.out.println("none found");
}
Or use short-circuiting Stream::anyMatch
to check if the filtered stream contains at least one matching entry:或者使用短路Stream::anyMatch
来检查过滤后的 stream 是否包含至少一个匹配条目:
if (commits.values().stream()
.map(Commit::getLogMessage) // equals should be equivalent to compareTo == 0
.anyMatch(commitMessageToSearch::equals))
{
commits.values().stream()
.filter(commit -> commit.getLogMessage().compareTo(commitMessageToSearch) == 0)
.map(Commit::getSha)
.forEach(System.out::println);
} else {
System.out.println("none found");
}
But this is definitely more verbose than for-loop
solution.但这绝对比for-loop
解决方案更冗长。
You want this:你要这个:
commits.values()
.stream()
.filter(commit -> commit.getLogMessage().compareTo(commitMessageToSearch) == 0)
.findFirst()
.map(Commit::getSha)
.ifPresentOrElse(
System.out::println, // if present, print out sha
() -> System.out.println("aksdhlkasj")); // print some garbage otherwise
Basically, you filter out the unwanted commits.基本上,您过滤掉不需要的提交。 Once you find a correct one, the method Stream#findfirst
short-circuits the processing as long as there is no need to search further.一旦找到正确的,只要不需要进一步搜索,方法Stream#findfirst
就会使处理短路。 For that reason, you might want to add break
in your for a loop.因此,您可能希望在 for 循环中添加break
。 Finally, extract sha
from the Commit
using Optional#map
and then Optional#ifPresentOrElse
handles both situation if such commit is present or not.最后,使用Optional#map
从Commit
中提取sha
,然后Optional#ifPresentOrElse
处理这两种情况,无论是否存在此类提交。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.