在流中使用 Java 8 foreach 循环移动到下一项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32654929/
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
Move to next item using Java 8 foreach loop in stream
提问by Viktor V.
I have a problem with the stream of Java 8 foreach attempting to move on next item in loop. I cannot set the command like continue;
, only return;
works but you will exit from the loop in this case. I need to move on next item in loop. How can I do that?
我对 Java 8 foreach 流尝试在循环中移动下一个项目时遇到问题。我无法设置像 一样的命令continue;
,只能return;
工作,但在这种情况下您将退出循环。我需要继续循环中的下一个项目。我怎样才能做到这一点?
Example(not working):
示例(不工作):
try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
filteredLines = lines.filter(...).foreach(line -> {
...
if(...)
continue; // this command doesn't working here
});
}
Example(working):
示例(工作):
try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
filteredLines = lines.filter(...).collect(Collectors.toList());
}
for(String filteredLine : filteredLines){
...
if(...)
continue; // it's working!
}
采纳答案by sstan
Using return;
will work just fine. It will not prevent the full loop from completing. It will only stop executing the current iteration of the forEach
loop.
使用return;
将工作得很好。它不会阻止完整循环完成。它只会停止执行forEach
循环的当前迭代。
Try the following little program:
试试下面的小程序:
public static void main(String[] args) {
ArrayList<String> stringList = new ArrayList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
stringList.stream().forEach(str -> {
if (str.equals("b")) return; // only skips this iteration.
System.out.println(str);
});
}
Output:
输出:
a
c
一个
c
Notice how the return;
is executed for the b
iteration, but c
prints on the following iteration just fine.
注意迭代return;
是如何执行的b
,但c
在接下来的迭代中打印得很好。
Why does this work?
为什么这样做?
The reason the behavior seems unintuitive at first is because we are used to the return
statement interrupting the execution of the whole method. So in this case, we expect the main
method execution as a whole to be halted.
行为起初看起来不直观的原因是因为我们习惯了return
中断整个方法执行的语句。因此,在这种情况下,我们希望整个main
方法执行停止。
However, what needs to be understood is that a lambda expression, such as:
但是,需要理解的是一个 lambda 表达式,例如:
str -> {
if (str.equals("b")) return;
System.out.println(str);
}
... really needs to be considered as its own distinct "method", completely separate from the main
method, despite it being conveniently located within it. So really, the return
statement only halts the execution of the lambda expression.
...确实需要被视为它自己独特的“方法”,与main
方法完全分开,尽管它很方便地位于其中。所以实际上,该return
语句只会停止 lambda 表达式的执行。
The second thing that needs to be understood is that:
需要理解的第二件事是:
stringList.stream().forEach()
... is really just a normal loop under the covers that executes the lambda expression for every iteration.
...实际上只是一个普通的循环,它为每次迭代执行 lambda 表达式。
With these 2 points in mind, the above code can be rewritten in the following equivalent way (for educational purposes only):
考虑到这 2 点,上面的代码可以用以下等效方式重写(仅用于教育目的):
public static void main(String[] args) {
ArrayList<String> stringList = new ArrayList<>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
for(String s : stringList) {
lambdaExpressionEquivalent(s);
}
}
private static void lambdaExpressionEquivalent(String str) {
if (str.equals("b")) {
return;
}
System.out.println(str);
}
With this "less magic" code equivalent, the scope of the return
statement becomes more apparent.
有了这个“不那么神奇”的等价代码,return
语句的范围变得更加明显。
回答by Hassan
You can use a simple if
statement instead of continue. So instead of the way you have your code, you can try:
您可以使用简单的if
语句代替 continue。因此,您可以尝试:
try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
filteredLines = lines.filter(...).foreach(line -> {
...
if(!...) {
// Code you want to run
}
// Once the code runs, it will continue anyway
});
}
The predicate in the if statement will just be the opposite of the predicate in your if(pred) continue;
statement, so just use !
(logical not).
if 语句中的谓词将与您的if(pred) continue;
语句中的谓词相反,因此只需使用!
(logical not)。
回答by John Bollinger
The lambda you are passing to forEach()
is evaluated for each element received from the stream. The iteration itself is not visible from within the scope of the lambda, so you cannot continue
it as if forEach()
were a C preprocessor macro. Instead, you can conditionally skip the rest of the statements in it.
您传递给的 lambdaforEach()
是针对从流中接收到的每个元素进行评估的。迭代本身在 lambda 的范围内是不可见的,因此您不能将continue
其视为forEach()
C 预处理器宏。相反,您可以有条件地跳过其中的其余语句。
回答by Anarkopsykotik
Another solution: go through a filter with your inverted conditions : Example :
另一种解决方案:通过您的倒置条件过滤器:示例:
if(subscribtion.isOnce() && subscribtion.isCalled()){
continue;
}
can be replaced with
可以替换为
.filter(s -> !(s.isOnce() && s.isCalled()))
The most straightforward approach seem to be using "return;" though.
最直接的方法似乎是使用“返回”;尽管。