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


    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 + "  ");
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    输出结果:

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

    结论:上述代码可知,没有打印出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();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    可以看出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 后继续执行");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    这里发现,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 后继续执行");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12


    结论: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) {}
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

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

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

  • 相关阅读:
    【算法题】2903. 找出满足差值条件的下标 I
    [附源码]计算机毕业设计springboot少儿节目智能推荐系统
    机器学习中的 SVM(支持向量机)和随机森林及其优缺点
    机器学习(14)---逻辑回归(含手写公式、推导过程和手写例题)
    Vue3.0 响应式reactive的原理实现
    strict模式表
    探索C语言结构体:编程中的利器与艺术
    防火墙基础实验配置
    修改element-UI组件样式
    [LeetCode319周赛] 环图,最大公因数,中心扩展+DP
  • 原文地址:https://blog.csdn.net/weixin_44976692/article/details/125905347