StackOverflow上看到一个以前没有意识到的问题,怎样能跳出forEach循环呢?
问题
我的第一想法是,break
不可以使用吗?continue
呢?
探索
于是我在IDEA中试了一下:
1 2 3 4 5 6 7 8 9 10 11 12
| @Test void testBreak() { LinkedList<Integer> integers = new LinkedList<Integer>(Collections.singleton(10)); Random random = new Random(); for (int i = 0; i < 10; i++) { integers.add(random.nextInt(20)); } integers.forEach((number) -> { System.out.println("Number: " + number); break; }); }
|
结果编译时报错:

接着我试了continue
,同样报错。
那怎么办了?
我接着试了return
:
1 2 3 4 5 6 7 8 9 10
| @Test void testBreak() { List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); integers.forEach((number) -> { System.out.println("Number: " + number); if (number == 2) { return; } }); }
|
运行结果:

没卵用
然后我发现粗心的把输出语句写在return上面了
1 2 3 4 5 6 7 8 9 10
| @Test void testBreak() { List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); integers.forEach(number -> { if (number == 2) { return; } System.out.println("Number: " + number); }); }
|
结果如下:

相当于continue
continue替代者找到了,那如何实现break呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class BreakException extends RuntimeException{ } ... @Test void testBreak() { List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); try { integers.forEach(number -> { if (number == 2) { throw new BreakException(); } System.out.println("Number: " + number); }); } catch (BreakException e) { System.out.println("Break"); } }
|
结果:

总结
forEach()方法不支持break、continue,是因为源码中:
1 2 3 4 5 6
| default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
|
for循环是在方法体内的,如果在forEach的lambda表达式中使用break和continue,是没有效果的。我们找到的替代方法是使用return;达到continue的效果,使用throw异常的方式取得和break一样的效果。
但是感觉有点麻烦了,不如还是直接使用增强for循环遍历。