我有一个问题与流的Java 8 foreach试图移动下一个项目在循环。我不能设置命令像继续;,只有返回;工作,但在这种情况下,您将退出循环。我需要继续循环中的下一个项目。我该怎么做呢?
例子(工作):
try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
filteredLines = lines.filter(...).foreach(line -> {
...
if(...)
continue; // this command doesn't working here
});
}
例子(工作):
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!
}
使用返回;会工作得很好。它不会阻止整个循环的完成。它只会停止执行forEach循环的当前迭代。
试试下面的小程序:
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);
});
}
输出:
一个
c
注意如何返回;在b迭代中执行,但是在接下来的迭代中打印c也很好。
为什么会这样?
这种行为起初看起来不太直观的原因是因为我们习惯了return语句中断整个方法的执行。所以在这种情况下,我们期望主方法的执行作为一个整体被停止。
然而,需要理解的是lambda表达式,例如:
str -> {
if (str.equals("b")) return;
System.out.println(str);
}
... Really需要被视为它自己独特的“方法”,完全独立于主方法,尽管它很方便地位于主方法中。实际上,return语句只是停止了lambda表达式的执行。
第二件需要理解的事情是:
stringList.stream().forEach()
... 实际上只是一个普通的循环,为每次迭代执行lambda表达式。
考虑到这两点,上面的代码可以用以下等价的方式重写(仅用于教学目的):
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);
}
使用这个“不那么神奇”的代码等效物,return语句的作用域变得更加明显。