首先说下不正确的打开方式:

第一:使用for循环删除集合的元素,示例代码如下

 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]

解说开始:

首先看下源码:

 public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
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
return oldValue;
}

解释:第一次进for循环,i=0 ,调用remove方法删除第一位的元素, 集合大小收缩,第一次删除完成后,list变成【b,c,d】;再次循环,i=1,调用remove方法删除了c 集合大小再次收缩,list变成【b,d】;再次循环,i=2,不符合条件,循环结束

第二:使用foreach循环删除元素,示例代码如下

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

结果:这段代码居然抛出了异常 java.util.ConcurrentModificationException。

解说开始:

首先看下源代码:

 public Iterator<E> iterator() {
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

解释:在Java中的foreach循环的工作原理就像一个iterator。

首次进入到foreach循环时,ArrayList创建一个内部迭代器类对象,以后循环就不再创建。每次循环的流程都是先调用迭代器对象的hasNext()方法,返回true,再调用next()方法,而每次调用next()方法时,首先会检测集合修改。
迭代器对象的实例字段就是检测的关键所在。实例字段在创建对象时赋值了一次,后面就没有再维护。
而调用remove(Object obj)方法时,集合本身跟踪改写操作(添加或者删除),ArrayLis类对象维护一个改写的变量,独立于迭代器对象维护的计数值。
内部迭代器类对象next()方法首先,判断集合的改写变量是否等于迭代器的改写值,不等于就抛出异常。
PS:
在测试中发现,若remove的是集合的倒数第二个元素或者最后一个元素,不会抛出异常。因为在remove以后,迭代器指向集合的末尾,再进入循环时,hasNext()方法返回false。循环结束。

so,接下来说下正确的打开方式——

方法一:用传统for循环,从集合最后元素向前循环删除元素,集合的size会变小,连带索引都会改变,但不会影响到前面的未循环元素。 示例代码如下
 ArrayList<Integer> a=new ArrayList<Integer>(15);
a.add(222);
a.add(3);
a.add(333);
a.add(000);
a.add(333);
a.add(4); for(int s=a.size()-1;s>=0;s--){
if(a.get(s).intValue()==333){
a.remove(s);
}
}
方法二:使用Iterator的remove()方法删除集合中的元素  示例代码如下
 privatevoid screenBlackNameList(List<SharedBoardSmsWrapper> source, List<BlackNameListModel> blackNameList){
Iterator<SharedBoardSmsWrapper> sourceIt=source.iterator();
while(sourceIt.hasNext()){
SharedBoardSmsWrapper tmpSharedBoardSmsWrapper=sourceIt.next();
Iterator<BlackNameListModel> blackNameListIt=blackNameList.iterator();
while(blackNameListIt.hasNext()){
BlackNameListModel tmpBlackNameListModel=blackNameListIt.next();
if(tmpSharedBoardSmsWrapper.getSource().equals(tmpBlackNameListModel.getSource())){
sourceIt.remove();
break;
}
}
}
}
 
 
 

Java循环删除集合多个元素的正确打开方式的更多相关文章

  1. (CSDN 迁移) JAVA循环删除List的某个元素

    若列表中只可能存在一个则可以用简单的循环删除,不多说. 若列表中可能存在多个,尤其是可能有多个连续的需要删除,用简单循环有可能发生异常. 需要使用迭代器(Iterator),两种具体实现: 逻辑上是一 ...

  2. for循环删除集合陷阱

    首先看下面的代码: import java.util.LinkedList;import java.util.List; public class DeleteCollection {         ...

  3. 集合赋值及for循环删除符合条件的元素

    一.Java语言中ArrayList对象能直接赋值给另一个ArrayList对象吗? https://zhidao.baidu.com/question/399214655.html ArrayLis ...

  4. ArrayList之foreach循环删除倒数第二个元素,不触发fail-fast机制

    今天一朋友问了个问题,对于如下一段代码,运行后会有怎样的结果? public class ArrayListTest { public static void main(String[] args) ...

  5. Python笔记:用for循环删除列表中的元素

    for运行过程中会有一个指针来记录当前循环的元素是哪一个,一开始这个指针指向第0个元素,然后获取它,接着删除第0个元素,这时候,原来是第1个的元素会变成第0个,当指针向后移动一次,指向了现在第1个元素 ...

  6. python循环删除list中的元素

    直接上例子: a = [1,2,3,4,5,6] for i in a: a.remove(i) print(a) 返回:[2, 4, 6] 循环a,想删除a的所有元素,但实际确有数据保留了下来,这是 ...

  7. Java思考——HashSet集合如何保证元素的唯一性也就是不包含重复元素?

    首先将源码逐级找出来1.HashSet<String> hs=new HashSet<String>();         hs.add("hello"); ...

  8. C#实现在foreach中删除集合中的元素

    List<string> str = new List<string>(); str.Add( "zs"); str.Add("ls") ...

  9. java的取出map里所有元素的两种方式

    /* * 取出map元素的两种方式 */package com.map.test; import java.util.HashMap;import java.util.Iterator;import ...

随机推荐

  1. [比较老的文章]三维渲染引擎 OGRE 与 OSG 的比较综述

    1 .引言随着计算机可视化.虚拟现实技术的飞速发展,人们对实时真实感渲染以及场景复杂度提出了更高的要求.传统的直接使用底层图形接口如OpenGL.DirectX开发图形应用的模式越来越暴露出开发复杂性 ...

  2. 采用重写tostring方法使ComboBox显示对象属性

    当ComboBox中添加的是对象集合的时候,如果运行就会发现显示是的命令空间.类名,而如果我们想显示对象属性名的时候,我们就可以在对象类中重写object基类中的tostring方法.

  3. 动态创建script在IE中缓存js文件时导致编码不正确bug

    $.each(scripts, function(){ if(!jsExist(this.src)){ var s = document.createElement("SCRIPT" ...

  4. sdn

    #!/usr/bin/env python #from mininet.cli import CLI #from mininet.link import Link #from mininet.net ...

  5. Python爬网获取全国各地律师电话号

    [本文出自天外归云的博客园] 从64365网站获取全国各地律师电话号,用到了python的lxml库进行对html页面内容的解析,对于xpath的获取和正确性校验,需要在火狐浏览器安装firebug和 ...

  6. Android first --- 网络编程

    网络编程 ###图片下载查看 1.发送http请求 URL url = new URL(address); //获取连接对象,并没有建立连接 HttpURLConnection conn = (Htt ...

  7. 注释声明:TODO HACK XXX FIXME REVIEW

    注释有时候也可以用来给一段代码声明额外的信息.这些声明的格式以单个单词打头并紧跟一个冒号.可以使用的声明如下. TODO: 说明代码还未完成.应当包含下一步要做的事情. HACK: 表明代码实现走了一 ...

  8. android appwigt

    package com.example.test1; import android.os.Bundle; import android.app.Activity; import android.con ...

  9. [OC][地图] 高德地图之定位初探(一)

    使用前的说明 高德地图开放平台的iOS定位模块网址-->http://lbs.amap.com/api/ios-location-sdk/summary/ 高德地图有Web端.android平台 ...

  10. [POJ2069]Super Star(模拟退火)

    题目链接:http://poj.org/problem?id=2069 题意:求一个半径最小的球,使得它可以包围住所有点. 模拟退火,圆心每次都去找最远那个点,这样两点之间的距离就是半径,那么接下来移 ...