`

foreach 循环不能改变集合中各项的值

阅读更多
import java.util.ArrayList;
import java.util.List;
public class foclass4 {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		List<String> lists = new ArrayList<String>();
		lists.add("ad");
		lists.add("dv");
		lists.add("dvs");
		lists.add("adf");
		for(String s:lists)
        {
        	if(s.equals("ad"))
        	{
        	   lists.remove(s);
        	   continue;
        	}
        	System.out.println("删除后--"+s);
        }
	}
}


报错:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at foclass4.main(foclass4.java:13)

原因:
就是针对使用foreach的语法,你要用foreach这种语法就必须继承这个接口Iterator,这个接口很简单,就是返回迭代器Iterator,迭代器有个特点就是快速失败的,通过迭代器迭代不能去移除集合中元素

详细JDK
如果多个线程同时访问一个 ArrayList 实例,而其中至少一个线程从结构上修改了列表,那么它必须 保持外部同步。(结构上的修改是指任何添加或删除一个或多个元素的操作,或者显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedList 方法将该列表“包装”起来。这最好在创建时完成,以防止意外对列表进行不同步的访问:

        List list = Collections.synchronizedList(new ArrayList(...)); 此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。

注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。



可以从迭代器中移除
List<String> lists = new ArrayList<String>();
		lists.add("ad");
		lists.add("dv");
		lists.add("dvs");
		lists.add("adf");
		
		Iterator<String> it=lists.iterator();
		while(it.hasNext())
		{
		   String str=it.next();
			if("ad".equals(str))
			{
			    it.remove();
			}
			else
			{
				System.out.println(str);
			}
		}

结果:
dv
dvs
adf
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics