使用ForEach转换为lambda表达式以进行中断循环

时间:2017-09-11 18:30:08

标签: for-loop lambda foreach java-8

在for循环中使用以下代码和破坏行为:

package test;

import java.util.Arrays;
import java.util.List;

public class Test {

    private static List<Integer> integerList = Arrays.asList(1, 2, 3, 4);

    public static void main(String[] args) {
        countTo2(integerList);
    }

    public static void countTo2(List<Integer> integerList) {

        for (Integer integer : integerList) {
            System.out.println("counting " + integer);
            if (integer >= 2) {
                System.out.println("returning!");
                return;
            }
        }
    }
}

尝试使用forEach()使用Lambda表达它将改变行为,因为for循环不再破坏:

public static void countTo2(List<Integer> integerList) {

    integerList.forEach(integer -> {
        System.out.println("counting " + integer);
        if (integer >= 2) {
            System.out.println("returning!");
            return;
        }
    });
}

这实际上是有道理的,因为return;语句只在lambda表达式本身内部(在内部迭代中)强制执行而不是整个执行序列,所以有没有办法获得所需的行为(打破for loop)使用lambda表达式?

3 个答案:

答案 0 :(得分:3)

以下代码在逻辑上等同于您的代码:

public static void countTo2(List<Integer> integerList) {
    integerList.stream()
               .peek(i -> System.out.println("counting " + i))
               .filter(i -> i >= 2)
               .findFirst()
               .ifPresent(i -> System.out.println("returning!"));
}

如果您对任何事情感到困惑,请告诉我们!

答案 1 :(得分:2)

您正在寻找的是short-circuit终端操作,虽然这是这样做的方式:

integerList.stream()
            .peek(x -> System.out.println("counting = " + x))
            .filter(x -> x >= 2)
            .findFirst()
            .ifPresent(x -> System.out.println("retunrning"));

仅在处理sequential流时才是等效的。只要您添加parallel peek可能会显示您不希望的元素,因为没有定义processing order,但有encounter order - 意味着元素将是正确送入终端操作。

答案 2 :(得分:1)

我能想到的一种方法是使用anyMatch和反向:

if (integerList.stream().noneMatch(val -> val >= 2)) {
    System.out.println("counting " + val);
}

if (integerList.stream().anyMatch(val -> val >= 2)) {
    System.out.println("returning!");
}

但在内部会迭代列表两次,并且我认为不是最优的。