【学习记录 time:】Java8 Lambda 表达式中的 forEach 如何提前终止?

简介: 【学习记录 time:】Java8 Lambda 表达式中的 forEach 如何提前终止?

场景复现

public class ForEachTest {
    public static void main(String[] args) {
        String[] strs = {"java", "php", "python", "c++", "c#"};
        ArrayList<String> list = new ArrayList<>(Arrays.asList(strs));
        list.forEach(e -> {
            if (e.contains("python")) {
                System.out.print("终止或者跳出循环?  ");
                return;
            }
            System.out.print(e + "  ");
        });
    }
}

输出结果:

java  php  终止或者跳出循环?  c++  c#  

结论:上述代码可知,没有打印出python,我们为了要跳出循环用了return;但是事实上并没有跳出Foreach,继续执行了代码!也就是说这里的return其实相当于普通for循环中的continue关键词。

分析:我们平时在普通的for循环时使用break跳出循环,而在普通的for循环中使用不止会跳出循环,更是会直接返回整个方法结果。但是在java8的forEach中是不能使用“break”和“continue”的,

而return的意思也不是原来return代表的含义了,而是类似continue。

简单看看源码:

@Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        final Object[] es = elementData;
        final int size = this.size;
        for (int i = 0; modCount == expectedModCount && i < size; i++)
            action.accept(elementAt(es, i));
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    

可以看出forEach是一个方法,当然是用return来结束的,而且void,没有返回值。

解决方案

1.使用原始的增强for循环+return(idea有强大的提示功能)

public static void main(String[] args) {
        String[] strs = {"java", "php", "python", "c++", "c#"};
        ArrayList<String> list = new ArrayList<>(Arrays.asList(strs));
        for (String s : list) {
            if (s.contains("python")) {
                System.out.print("终止或者跳出循环?  ");
                return;
            }
            System.out.print(s + "  ");
        }
        System.out.println("return 后不执行,continue 后继续执行");
    }

这里发现,python以及后面的都未打印出来,return直接退出整个main方法;

2.使用原始的增强for循环+continue

public static void main(String[] args) {
        String[] strs = {"java", "php", "python", "c++", "c#"};
        ArrayList<String> list = new ArrayList<>(Arrays.asList(strs));
        for (String s : list) {
            if (s.contains("python")) {
                System.out.print("终止或者跳出循环?  ");
                continue;
            }
            System.out.print(s + "  ");
        }
        System.out.println("  ###return 后不执行,continue 后继续执行");
    }

结论:continue会执行后面的逻辑,所以后续逻辑需要执行的话建议使用continue来跳出for。

3.抛异常,做双重捕捉

在实际运行中,往往有很多不突发情况导致代码提前终止,比如:空指针异常,其实,我们也可以通过抛出假异常的方式来达到终止forEach()方法的目的

public static void main(String[] args) {
        String[] strs = {"java", "php", "python", "c++", "c#"};
        ArrayList<String> list = new ArrayList<>(Arrays.asList(strs));
        try {
            list.forEach(e -> {
                if (e.contains("python")) {
                    System.out.print("终止或者跳出循环?  ");
                    throw new RuntimeException("抛出异常");
                }
                System.out.print(e + "  ");
            });
        } catch (Exception ignored) {}
    }

结论:这里内层抛异常,外层捕获但不作处理,也实现了退出for循环。当然也可以抛出想要跑出的内容。

需要注意的一点是:要确保你forEach()方法体内不能有其它代码可能会抛出的异常与自己手动抛出并捕获的异常一样;不然捕获到其他异常又没做处理,这不就成了一个bug么!!!

相关文章
|
5天前
|
Java
Java中的控制流语句:if、switch、for、foreach、while、do-while
Java中的控制流语句包括条件判断语句 `if`和 `switch`,以及循环语句 `for`、增强型 `for`(`foreach`)、`while`和 `do-while`。这些语句提供了灵活的方式来控制程序的执行流程,确保代码逻辑清晰且易于维护。掌握这些基本语法,对于编写高效和可读的Java程序至关重要。
31 15
|
1天前
|
Java 调度 开发者
Java线程池ExecutorService学习和使用
通过学习和使用Java中的 `ExecutorService`,可以显著提升并发编程的效率和代码的可维护性。合理配置线程池参数,结合实际应用场景,可以实现高效、可靠的并发处理。希望本文提供的示例和思路能够帮助开发者深入理解并应用 `ExecutorService`,实现更高效的并发程序。
23 10
|
4天前
|
Java 数据库连接 数据库
【潜意识Java】深度分析黑马项目《苍穹外卖》在Java学习中的重要性
《苍穹外卖》项目对Java学习至关重要。它涵盖了用户管理、商品查询、订单处理等模块,涉及Spring Boot、MyBatis、Redis等技术栈。
25 4
|
4天前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
21 4
|
4天前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
15 1
|
1月前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
1月前
|
安全 Java API
Java中的Lambda表达式:简化代码的现代魔法
在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
|
2月前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
36 0
|
Java
QuartZ Cron表达式在java定时框架中的应用
CronTrigger CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表。 CronTrigger,你可以指定触发的时间表如“每星期五中午”,或“每个工作日9:30时”,甚至“每5分钟一班9:00和10:00逢星期一上午,星期三星期五“。
1110 0
|
18天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
80 17