Java8 lambda 表达式 forEach 如何提前终止?

首先,让我们看一下Java 8中如何使用forEach()方法。forEach()方法接受一个Consumer接口作为参数,该接口定义了一个accept()方法,该方法接受一个对象并对其执行一些操作。因此,我们可以通过Lambda表达式来实现Consumer接口。下面是一个使用Lambda表达式的forEach()方法的示例:

List<String> list = Arrays.asList("Java", "C++", "Python", "JavaScript");
list.forEach(s -> System.out.println(s));

在上面的代码中,我们创建了一个包含四个字符串的列表,并使用Lambda表达式来打印每个字符串。

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        list.forEach(i -> {
            if (i == 3) {
               return;
            }
            System.out.println(i);
        });
    }

执行结果

可以看出return没有起到作用,这是为什么?

然而,在某些情况下,我们可能需要在forEach()方法执行到某个元素时提前终止它的执行。在Java 8之前,我们可以使用break语句来实现这一点。但是,在Lambda表达式中,我们不能使用break语句。那么,在Lambda表达式中如何提前终止forEach()方法的执行呢?

使用Lambda表达式的forEach方法提前终止迭代

在某些情况下,我们希望在某个条件满足时提前终止迭代过程,以避免不必要的计算和资源浪费。那么,在这种情况下,我们可以使用Lambda表达式的forEach方法提前终止迭代。

为了实现提前终止迭代,我们可以在Lambda表达式中使用break语句来实现。但是,在Java8中,Lambda表达式并不支持使用break语句,所以我们需要使用其他的方式来实现提前终止迭代。

一种常见的方式是使用AtomicBoolean类型的变量作为标志来实现提前终止迭代。具体实现如下:

csharpCopy codeList<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
AtomicBoolean found = new AtomicBoolean(false);
list.forEach(i -> {
    if (i == 3) {
        found.set(true);
    }
    if (found.get()) {
        return;
    }
    System.out.println(i);
});

在上面的示例中,我们首先定义了一个AtomicBoolean类型的变量found作为标志。在Lambda表达式中,当元素为3时,我们将found标志设置为true,表示已经找到了满足条件的元素。接着,在每次迭代中,我们都会检查found标志是否已经为true,如果是,则直接返回,从而提前终止迭代。如果不是,则继续执行后续操作。

使用自定义的函数式接口来实现提前终止迭代

public interface BreakableConsumer<T> extends Consumer<T> {
    boolean isBreak();
}
 
public static <T> void forEachWithBreak(List<T> list, BreakableConsumer<? super T> action) {
    for (T t : list) {
        action.accept(t);
        if (action.isBreak()) {
            break;
        }
    }
}
 
public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    forEachWithBreak(list, i -> {
        if (i == 3) {
            return true;
        }
        System.out.println(i);
        return false;
    });
}

在上面的示例中,我们首先定义了一个自定义的函数式接口BreakableConsumer,它继承了Consumer接口,并新增了一个isBreak方法,用于判断是否需要提前终止迭代。接着,我们定义了一个forEachWithBreak方法,该方法接受一个BreakableConsumer类型的参数,并在迭代过程中判断是否需要提前终止迭代。最后,在main方法中,我们使用forEachWithBreak方法并传递一个Lambda表达式作为参数来进行迭代操作。

为什么foreach使用return语句无法生效?

在Lambda表达式中,使用return语句无法生效的原因是,Lambda表达式本身并不是一个独立的代码块,它是一个函数式接口的实现。在Lambda表达式中使用return语句只会返回当前Lambda表达式的执行结果,而不会影响forEach方法的迭代过程。因此,如果希望在Lambda表达式中提前终止迭代,必须使用其他的方式来实现。

猜你喜欢

转载自blog.csdn.net/Dark_orange/article/details/131570012