zoukankan      html  css  js  c++  java
  • Java循环中删除一个列表元素

    本文主要想讲述一下我对之前看到一篇文章的说法。假设跟你的想法有出入,欢迎留言。一起讨论。

    #3. 在循环中删除一个列表元素

      考虑以下的代码。迭代过程中删除元素:

    ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
    for (int i = 0; i < list.size(); i++) {
    	list.remove(i);
    }
    System.out.println(list);

      这段代码的输出是:

    [b, d]
    

      这种方法有一个严重的问题。当元素被移除,该列表的大小缩减。元素索引也随之发生了变化。所以,假设你想通过使用索引来删除一个循环内的多个元素。就会导致错误的结果。

      你可能猜到能够使用iterator来删除循环中的元素。

    在Java中的foreach循环的工作原理就像一个iterator。 可是在这里也会错误发生。

    请看以下的代码:

    ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
     
    for (String s : list) {
    	if (s.equals("a"))
    		list.remove(s);
    }

      上面的foreach loop代码会抛出一个异常ConcurrentModificationException. 可是以下这段代码不会。

    ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
    Iterator<String> iter = list.iterator();
    while (iter.hasNext()) {
    	String s = iter.next();
     
    	if (s.equals("a")) {
    		iter.remove();
    	}
    }

      通过分析ArrayList.iterator()的原代码,我们能够发现next()方法必需要在remove()方法前被调用。

    在foreach loop中。编译器产生的代码会先调用next()方法,从而产生异常。

    以上这段是拷贝过来的。可是我自己去看了源代码以及測试过后,发现并非这样。

    不是由于先调用next()方法或者先调用remove()方法导致出错。而是remove()和remove(Object o)之间的差异。查看源代码,能够看到remove()方法里有一个“expectedModCount = modCount;”语句;而在remove(Object o)方法是这种“modCount++;”它没有对expectedModCount做处理。导致在checkForComodification()方法推断“expectedModCount == modCount”时出错。

    所以无论在什么时候,仅仅要你调用了remove(Object o)方法,然后又调用了next()方法。都一定会报ConcurrentModificationException这个异常的。

    上面所说的“上面的foreach loop”的情况就是属于这一现象。

    大家能够试一下将remove()方法摆在next()方法前,是能够用的。

  • 相关阅读:
    1101. Quick Sort (25)
    1100. Mars Numbers (20)
    1099. Build A Binary Search Tree (30)
    TCP四次挥手为何需要TIME_WAIT以及为何是2MSL?
    关于priority_queue运算符重载的问题
    leetcode151.翻转字符串里的单词
    华为笔试题--最长公共子串
    华为笔试题--表达式求值
    华为笔试题--字符串合并处理
    华为笔试题--删除字符串中出现次数最少的字符
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7162669.html
Copyright © 2011-2022 走看看