【学习记录 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么!!!

相关文章
|
9月前
|
存储 Oracle Java
java零基础学习者入门课程
本课程为Java零基础入门教程,涵盖环境搭建、变量、运算符、条件循环、数组及面向对象基础,每讲配示例代码与实践建议,助你循序渐进掌握核心知识,轻松迈入Java编程世界。
698 0
|
9月前
|
负载均衡 Java API
grpc-java 架构学习指南
本指南系统解析 grpc-java 架构,涵盖分层设计、核心流程与源码结构,结合实战路径与调试技巧,助你从入门到精通,掌握高性能 RPC 开发精髓。
840 8
|
9月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
437 1
|
10月前
|
Java
Java基础学习day08-作业
本作业涵盖Java中Lambda表达式的应用,包括Runnable与Comparator接口的简化实现、自定义函数式接口NumberProcessor进行加减乘及最大值操作,以及通过IntProcessor处理整数数组,实现遍历、平方和奇偶判断等功能,强化函数式编程实践。
146 5
|
10月前
|
Java API 容器
Java基础学习day08-2
本节讲解Java方法引用与常用API,包括静态、实例、特定类型方法及构造器引用的格式与使用场景,并结合代码示例深入解析。同时介绍String和ArrayList的核心方法及其实际应用。
245 1
|
10月前
|
Java 程序员
Java基础学习day08
本节讲解Java中的代码块(静态与实例)及其作用,深入介绍内部类(成员、静态、局部及匿名)的定义与使用,并引入函数式编程思想,重点阐述Lambda表达式及其在简化匿名内部类中的应用。
225 5
|
10月前
|
Java
Java基础学习day07-作业
本作业包含六个Java编程案例:1)动物类继承与多态;2)加油卡支付系统;3)员工管理类设计;4)学生信息统计接口;5)USB设备控制;6)家电智能控制。综合运用抽象类、接口、继承、多态等面向对象技术,强化Java基础编程能力。
308 3
|
10月前
|
Java
Java基础学习day06-作业
本内容为Java基础学习作业,涵盖两个案例:一是通过Card类及其子类GoldenCard、SilverCard实现加油卡系统,体现封装与继承;二是通过Shape类及子类Circle、Rectangle演示多态与方法重写,强化面向对象编程理解。
156 1
|
10月前
|
设计模式 存储 Java
Java基础学习day07
本节讲解Java中的final关键字、单例设计模式、枚举类、抽象类与接口。涵盖常量定义、单例写法(饿汉式/懒汉式)、枚举特点及应用场景,以及抽象类与接口的使用与区别,助力掌握核心面向对象编程思想。
312 1
|
10月前
|
Java
Java基础学习day05-作业
本文为Java基础学习第五天作业,通过五个案例练习类与对象的定义、构造方法、set/get方法及成员方法的应用。涵盖女友、学生、教师、手机和电影等类的设计与测试,强化面向对象编程基础。
164 2