Java增强for循环的增删操作代码

 更新时间:2024年02月07日 10:37:50   作者:loet6010  
Foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素,本文通过实例演示普通for循环和foreach循环使用,java增强for循环的操作代码感兴趣的朋友一起看看吧

最近在看Java开发手册时,看到这样一条规定:

下面就来一探究竟,看看为什么会有这样的规定。
Foreach循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素。foreach语法格式如下:

for( 元素类型T 元素变量t : 遍历对象obj){
	引用了t 的java 语句;
}

以下实例演示了普通for循环和foreach循环使用:

    private static void test() {
        List<String> names = new ArrayList<String>() {{
            add("Hello");
            add("World");
            add("Good");
        }};
        System.out.println("foreach循环");
        for (String name : names) {
            System.out.println(name);
        }
        System.out.println("普通for循环");
        for (int i = 0; i < names.size(); i++) {
            System.out.println(names.get(i));
        }
    }

输出结果如下:

foreach循环
Hello
World
Good
普通for循环
Hello
World
Good

可以看到,使用foreach语法遍历集合或者数组的时候,可以起到和普通for循环同样的效果,并且代码更加简洁。所以,foreach循环也通常也被称为增强for循环。

其实,增强for循环是Java给我们提供的一个语法糖,如果将以上代码编译后的class 文件进行反编译的话,可以得到以下代码:

    private static void test() {
        List<String> names = new ArrayList<String>() {
            {
                this.add("Hello");
                this.add("World");
                this.add("Good");
            }
        };
        System.out.println("foreach循环");
        Iterator var1 = names.iterator();

        while(var1.hasNext()) {
            String name = (String)var1.next();
            System.out.println(name);
        }

        System.out.println("普通for循环");

        for(int i = 0; i < names.size(); ++i) {
            System.out.println((String)names.get(i));
        }

    }

可以发现,原来增强for循环是依赖了while循环和Iterator实现的。规范中指出不让我们在foreach循环中对集合元素做add/remove操作,那么,我们尝试着做一下看看会发生什么问题。

    private static void test() {
        List<String> names = new ArrayList<String>() {{
            add("Hello");
            add("World");
            add("Good");
        }};
        System.out.println("增强for循环");
        for (String name : names) {
            System.out.println(name);
            if ("Hello".equals(name)) {
                names.remove(name);
            }
        }
    }
增强for循环
Hello
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
	at java.util.ArrayList$Itr.next(ArrayList.java:861)

可以看到抛出了异常,追踪异常中的checkForComodification如下:

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

这是ArrayList中的检测代码,那么这个modCount和expectedModCount又是什么东西呢?
通过翻源码,我们可以发现:
●● modCount是ArrayList中的一个成员变量。它表示该集合实际被修改的次数。
●● expectedModCount是ArrayList中的一个内部类——Itr中的成员变量。expectedModCount 表示这个迭代器期望该集合被修改的次数。其值是在ArrayList.iterator方法被调用的时候初始化的。只有通过迭代器对集合进行操作,该值才会改变。
●● Itr是一个Iterator的实现,使用ArrayList.iterator方法可以获取到的迭代器就是Itr类的实例。
他们之间的关系如下:

class ArrayList{
	private int modCount;
	public void add();
	public void remove();
	private class Itr implements Iterator<E> {
		int expectedModCount = modCount;
	}
	public Iterator<E> iterator() {
		return new Itr();
	}
}

remove方法核心逻辑如下:

    /*
     * Private remove method that skips bounds checking and does not
     * return the value removed.
     */
    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

可以看到,它只修改了modCount,并没有对expectedModCount做任何操作。

之所以会抛出ConcurrentModificationException异常,是因为我们的代码中使用了增强for循环,而在增强for循环中,集合遍历是通过iterator进行的,但是元素的add/remove却是直接使用的集合类自己的方法。这就导致iterator在遍历的时候,会发现有一个元素在自己不知不觉的情况下就被删除/ 添加
,就会抛出一个异常,用来提示用户,可能发生了并发修改。

因此当我们确实有需求需要删除其中一部分元素时,因该如java手册建议的那样使用Iterator进行操作。

    private static void test() {
        List<String> names = new ArrayList<String>() {{
            add("Hello");
            add("World");
            add("Good");
        }};
        Iterator iterator = names.iterator();
        while (iterator.hasNext()) {
            if (iterator.next().equals("Hello")) {
                iterator.remove();
            }
        }
    }

到此这篇关于Java增强for循环的增删操作的文章就介绍到这了,更多相关Java增强for循环内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot集成整合JWT与Shiro流程详解

    SpringBoot集成整合JWT与Shiro流程详解

    安全管理是软件系统必不可少的的功能。根据经典的“墨菲定律”——凡是可能,总会发生。如果系统存在安全隐患,最终必然会出现问题,这篇文章主要介绍了SpringBoot集成JWT、Shiro框架的使用
    2022-12-12
  • mybatis映射文件操作存储过程的实现

    mybatis映射文件操作存储过程的实现

    本文主要介绍了mybatis映射文件操作存储过程的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • 基于Java POI实现动态列Excel导出的通用方法

    基于Java POI实现动态列Excel导出的通用方法

    在企业级开发中,Excel导出功能是常见需求,当面对前端动态传参、列数不确定的场景时,编写通用的动态列导出方法能显著提升开发效率,本文将结合Java POI框架,详细解析如何实现支持多级表头、动态列求和及合并单元格的Excel导出功能,并提供完整代码示例与使用说明
    2025-07-07
  • Spring @Transactional注解的声明式事务简化业务逻辑中的事务管理

    Spring @Transactional注解的声明式事务简化业务逻辑中的事务管理

    这篇文章主要为大家介绍了Spring @Transactional注解的声明式事务简化业务逻辑中的事务管理,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 使用Java代码发送携带附件的邮件的示例详解

    使用Java代码发送携带附件的邮件的示例详解

    本文介绍如何使用Hutool库的MailUtil组件实现邮件发送功能,包括设置邮件服务器、账号认证、邮件内容及附件等步骤,需要的朋友可以参考下
    2025-08-08
  • 使用BufferedReader读取TXT文件中数值,并输出最大值

    使用BufferedReader读取TXT文件中数值,并输出最大值

    这篇文章主要介绍了使用BufferedReader读取TXT文件中数值,并输出最大值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 初识Spring Boot框架和快速入门

    初识Spring Boot框架和快速入门

    这篇文章主要介绍了初识Spring Boot框架学习,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • idea 普通文件夹 转换成 module操作

    idea 普通文件夹 转换成 module操作

    这篇文章主要介绍了idea 普通文件夹 转换成 module操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Java高级-反射&动态代理详解

    Java高级-反射&动态代理详解

    这篇文章主要介绍了Java高级-反射&动态代理详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • Java后端向前端推送消息完整代码实例

    Java后端向前端推送消息完整代码实例

    WebSocket是一种全双工通信协议,允许后端主动向前端推送消息,下面这篇文章主要介绍了Java后端向前端推送消息的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2026-02-02

最新评论