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循环内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实现英文翻译程序

    java实现英文翻译程序

    这篇文章主要为大家详细介绍了java实现英文翻译程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06
  • 详解java 拼音首字母搜索内容功能的示例

    详解java 拼音首字母搜索内容功能的示例

    这篇文章主要介绍了详解java 拼音首字母搜索内容功能的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Spring+Mybatis 实现aop数据库读写分离与多数据库源配置操作

    Spring+Mybatis 实现aop数据库读写分离与多数据库源配置操作

    这篇文章主要介绍了Spring+Mybatis 实现aop数据库读写分离与多数据库源配置操作,需要的朋友可以参考下
    2017-09-09
  • Java分治法与二分搜索算法实例分析

    Java分治法与二分搜索算法实例分析

    这篇文章主要介绍了Java分治法与二分搜索算法,简单讲述了分治法与二分搜索算法的原理并结合java实例分析了二分搜索算法的实现与使用技巧,需要的朋友可以参考下
    2017-11-11
  • 如何获得spring代理对象的原对象

    如何获得spring代理对象的原对象

    这篇文章主要介绍了如何获得spring代理对象的原对象的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • springboot自定义Starter过程解析

    springboot自定义Starter过程解析

    这篇文章主要介绍了springboot自定义Starter过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • 如何基于ssm框架实现springmvc拦截器

    如何基于ssm框架实现springmvc拦截器

    这篇文章主要介绍了如何基于ssm框架实现springmvc拦截器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • SpringBoot Redis清除所有的key的实现方法

    SpringBoot Redis清除所有的key的实现方法

    本文主要介绍了SpringBoot Redis清除所有的key的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • springcloud集成nacos 使用lb 无效问题解决方案

    springcloud集成nacos 使用lb 无效问题解决方案

    这篇文章主要介绍了解决springcloud集成nacos 使用lb 无效,通过查看spring-cloud-starter-gateway jar中的自动配置类的源码,得知,该jar包中是不支持负载均衡的,需要引入spring-cloud-starter-loadbalancer 来支持,需要的朋友可以参考下
    2023-04-04
  • Java 断言 assert的用法详解

    Java 断言 assert的用法详解

    Java assert断言机制是Java5中推出的新特性,它主要用于在程序运行时检查状态或假设的正确性,本篇文章将全面详细地讲解Java assert断言机制,包括断言概述、语法规则、工作原理、使用场景、注意事项以及示例代码等方面,需要的朋友可以参考下
    2023-05-05

最新评论