`
ncs123
  • 浏览: 102944 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

ArrayList for遍历删除分析

    博客分类:
  • java
阅读更多
一、案例
//案例一
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        for (String item : list) {
            if ("1".equals(item)) {
                list.remove(item);
            }
        }
    } //运行不报错

//案例二
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        for (String item : list) {
            if ("2".equals(item)) {
                list.remove(item);
            }
        }
    } //运行报错Exception in thread "main" java.util.ConcurrentModificationException


二、javap反编译后字节码分析
public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: new           #2                  // class java/util/ArrayList
         3: dup
         4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #4                  // String 1
        11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #6                  // String 2
        20: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: invokeinterface #7,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
        32: astore_2
        33: aload_2
        34: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
        39: ifeq          72
        42: aload_2
        43: invokeinterface #9,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        48: checkcast     #10                 // class java/lang/String
        51: astore_3
        52: ldc           #6                  // String 2
        54: aload_3
        55: invokevirtual #11                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        58: ifeq          69
        61: aload_1
        62: aload_3
        63: invokeinterface #12,  2           // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z
        68: pop
        69: goto          33
        72: return

    21-25行:java编译器把for循环编译成List.iterator,然后通过Iterator.hasNext,Iterator.next遍历,然后checkcast指令String类型校验

三、源码分析



1. 调用ArrayList.iterator(),返回Iterator对象
2. 标记5是Iterator对象的remove(),标记6是ArrayList的remove()
3. cursor是Iterator当前指针,lastRet是Iterator上次遍历的指针,modCount是ArrayList的变更次数,当add(1),add(2),remove(1)时,modCount=3

案例一分析:
    1. add(1),add(2),for遍历 : modCount=2,expectedModCount=2,cursor=0,size=2
    2. Iterator.hasNext():返回true
    3. Iterator.next():标记3的checkForComodification()校验成功,返回字符串“1”
    4. equals=true,调用标记6的ArrayList的remove():modCount=3,expectedModCount=2,cursor=1,size=1
    5. Iterator.hasNext():返回false,退出循环
    总结:根本就没有遍历第二个字符串“2”

案例二分析:
    1. add(1),add(2),for遍历 : modCount=2,expectedModCount=2,cursor=0,size=2
    2. Iterator.hasNext():返回true
    3. Iterator.next():标记3的checkForComodification()校验成功,返回字符串“1”
    4. equals=false:modCount=2,expectedModCount=2,cursor=1,size=2
    5. Iterator.hasNext():返回true
    6. Iterator.next():标记3的checkForComodification()校验成功,返回字符串“2”
    7. equals=true,调用标记6的ArrayList的remove():modCount=3,expectedModCount=2,cursor=2,size=1
    8. Iterator.hasNext():返回true
    9. Iterator.next():标记3的checkForComodification()校验失败,modCount != expectedModCount抛异常ConcurrentModificationException

总结:
    1. ArrayList.remove()方法不会更新expectedModCount,cursor,只更改了原数组,size,modCount等数据,由于数据不一致导致校验失败。
    2. Iterator.remove()方法会更新原数组,size,modCount等数据。
  • 大小: 116.1 KB
  • 大小: 112.2 KB
分享到:
评论

相关推荐

    Java ArrayList遍历修改代码实例解析

    在遍历 ArrayList 时,不能使用传统的 for 循环来删除元素,因为这将导致 ConcurrentModificationException 异常。相反,我们可以使用以下三种方法来遍历和删除 ArrayList 元素: ### 1. 使用迭代器(Iterator) ...

    浅谈普通for循环遍历LinkedList弊端

    在ArrayList中,元素存储在一个连续的内存区域,通过索引可以直接访问到元素,因此对于ArrayList,使用for循环遍历是非常高效的操作,因为get方法可以通过索引快速访问元素,时间复杂度为O(1)。 但是,当使用普通...

    java ArrayList的使用与分析

    - **遍历元素**:可以使用 `for-each` 循环或迭代器进行遍历。 - **修改元素**:`list.set(index, newValue);` 3. **ArrayList 的重要方法和属性** - **构造器**: - 默认构造器:`ArrayList()`,初始容量为16...

    java arrayList遍历的四种方法及Java中ArrayList类的用法

    - **增强型for循环(foreach)遍历**(方法3):Java 5引入的语法糖,适用于实现了Iterable接口的对象,如ArrayList。 ```java for(String tmp : list){ System.out.println(tmp); } ``` - **索引遍历**...

    ArrayList数据结构的分析

    由于ArrayList支持随机访问,所以通过for-each循环或迭代器进行遍历非常高效。`ListIterator`提供了双向遍历的功能,可以向前或向后移动。 7. **线程安全性**: ArrayList本身不是线程安全的,这意味着在多线程...

    Java遍历集合方法分析(实现原理、算法性能、适用场合)_.docx

    本文将深入分析Java中三种主要的遍历集合方法:传统的for循环遍历、迭代器遍历以及foreach循环遍历。 1. **传统的for循环遍历**: 这种方式依赖于计数器,开发者需要手动初始化并维护计数器,依次读取集合中的每个...

    java数组遍历 删除remove(示例代码)

    在这个例子中,使用了for循环来遍历ArrayList。循环变量`i`从0开始,直到`aa.size()`(当前集合的大小),每次迭代都会获取并打印出集合中相应位置的对象。`aa.get(i)`用于获取索引为`i`的元素,这里需要强制转换回`...

    ArrayList上机练习1

    总结来说,这个练习涵盖了`ArrayList`的基本操作,包括添加、删除、遍历和排序,同时也涉及了`Iterator`的使用和性能比较。通过这个练习,你可以加深对Java集合框架的理解,尤其是`ArrayList`和`Collections`工具类...

    ArrayList类操作程序实例

    六、遍历ArrayList 1. for-each循环:`for (E e : list) { ... }` 2. Iterator迭代器:`Iterator&lt;E&gt; iterator = list.iterator(); while (iterator.hasNext()) { E e = iterator.next(); ... }` 七、ArrayList的...

    JavaScript 实现基础 ArrayList 功能

    首先,我们需要创建一个ArrayList类,这个类将包含添加、删除、查找、更新和遍历元素等基本操作。由于JavaScript的Array对象已经提供了这些功能,我们可以通过扩展Array原型来创建ArrayList。 ```javascript ...

    JAVA提高第十篇 ArrayList深入分析

    6. 遍历:通过for循环遍历整个列表。 7. 多级存储:ArrayList可以包含其他集合,如在上述代码中,一个ArrayList包含了另一个ArrayList。 二、ArrayList的重要属性 ArrayList的核心属性是`elementData`,这是一个...

    day09-ArrayList集合&学生管理系统.pdf

    此部分内容介绍了如何创建一个存储字符串的ArrayList集合,并通过for循环实现遍历,遍历的过程中使用`get(index)`方法获取元素,使用`size()`方法获取集合的长度。 ### ArrayList存储学生对象并遍历 此部分讲解了...

    java中循环遍历删除List和Set集合中元素的方法(推荐)

    **错误的遍历删除方式** 错误的示例代码如下: ```java Set&lt;CheckWork&gt; set = this.getUserDao().getAll().get(0).getActionCheckWorks(); for (CheckWork checkWork : set) { if (checkWork.getState() == 1) { ...

    java集合类arraylist循环中删除特定元素的方法.docx

    然而,在遍历过程中直接修改`ArrayList`(如删除元素)可能会引发`IndexOutOfBoundsException`等异常。 #### 错误示例分析 以下是一种常见的错误操作方式: ```java for (int i = 0; i (); i++) { if (list.get...

    ArrayList.pdf

    可以使用for循环或增强for循环(也称for-each循环)来遍历ArrayList。此外,也可以使用Iterator或ListIterator迭代器进行遍历。 5. ArrayList的容量和扩容机制: 初始创建的ArrayList有一个默认的初始容量(通常...

    ArrayList演示

    首先,ArrayList的基本操作包括初始化、添加元素、删除元素、修改元素以及遍历元素。我们可以创建一个ArrayList对象,并指定其初始容量,例如: ```java ArrayList&lt;String&gt; list = new ArrayList(5); ``` 添加元素...

    用ArrayList实现用户信息的添加,删除,更新,查询

    在这个场景中,我们使用ArrayList来实现用户信息的添加、删除、更新和查询功能,这在实际的业务开发中非常常见,特别是对于小型数据集的操作。 **一、添加用户信息** 添加用户信息是通过调用ArrayList的`add()`...

    第03章 方法与数组 04 数组遍历和内存分析

    为了解决这些问题,Java提供了更高级的数据结构,如ArrayList和LinkedList,它们在内部实现了动态内存管理和优化的插入/删除操作,但牺牲了直接访问的效率。 总之,本章深入探讨了Java中的方法使用、数组遍历以及...

    用C语言模拟ArrayList

    ArrayList提供了在数组中添加、删除和查找元素的便利操作,而无需预先知道数组的大小。下面,我们将深入探讨如何用C语言实现ArrayList及其相关的知识点。 首先,`Array.c`文件通常会包含ArrayList的核心实现,包括...

Global site tag (gtag.js) - Google Analytics