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

第一:使用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. ML-分类与逻辑回归

    布尔分类(binary classification)问题: 训练集:$S=\{(x^{(i)}, y^{(i)})\}$ 输入:特征向量$x$ 期望输出:$y\in\{0, 1\}$ 这里使用的假设 ...

  2. CentOS 安装 Dubbo 管理控制台

    安装之前需要安装zookeeper详情http://www.cnblogs.com/zuge/p/6141101.html Dubbo 管控台可以对注册到 zookeeper 注册中心的服务或服务消费 ...

  3. 对一个二维数组进行升序排列a[0][1]为最小

    public static int[][] dyadicArraySort(int a[][]){ int temp=0;int sum =0;int nn=0; for(int i=0;i<a ...

  4. nginx安装方式

    1.首先安装pcre库 获取pcre到一个目录 wget http://ftp.exim.llorien.org/pcre/pcre-8.21.tar.gz 解压缩pcre包 tar -zxvf pc ...

  5. C++ STL之vector用法总结

    介绍 vector是表示可变大小数组的序列容器. 就像数组一样,vector也采用的连续存储空间来存储元素.也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效.但是又不像数组,它的大 ...

  6. Log4net(1):配置的简单说明

    基础代码下载地址:https://github.com/zhangsai521314/StudyLog4net 1:按日期分隔日志 <configSections> <section ...

  7. Express+mysql的博客(1)

    学了东西一定要自己上手试过才知道是不是真的会了.一直想练练node的使用,本来也没有什么好想法的,经同学提醒了一下,发现其实我可以用node写一个博客.我同学说工作量会非常之大╮(╯_╰)╭那也得先试 ...

  8. jQuery.eq() 函数

    eq() 函数 获取当前对象中指定索引所对应的的元素 语法 $selector.eq(index)//index为指定索引,值为数字型 返回值 返回值为一个对象 实例说明 代码 <!DOCTYP ...

  9. iOS - PackIpa App 打包

    前言 打包 ipa 的前提 证书的申请和设置和 "App 上架" 文章的一样 从第一步到第四步都是一样的.还有第六步的 1-3 都是一样的,从第四步开始变化. 1.Archive ...

  10. mysql存储过程语法及实例

    存储过程如同一门程序设计语言,同样包含了数据类型.流程控制.输入和输出和它自己的函数库. --------------------基本语法-------------------- 一.创建存储过程cr ...