标签:迭代 logs i++ turn print 线程 res equal .com
ps:一直以来对迭代器的问题理解不是很透彻,有必要好好的总结一下。
Iterator必须依附于Collection对象,若有一个Iterator对象,则必然有一个与之关联的Collection对象。
Iterator提供了两个方法来迭代访问Collection即合理的元素,并可通过remove()来删除集合中上一次next()方法返回的集合元素。
当使用Iterator迭代访问Collection集合元素时,Collection集合里的元素不能被改变,只有通过Iterator的remove()方法删除上一次next()方法返回的集合元素才可以;否则会引发java.util.ConcurrentModificationException异常。
之所以会出现这样的异常,是因为Iterator迭代器采用的是快速失败(fail-fast)机制,一旦在迭代过程中检测到该集合已经被修改(通常是程序中其它线程修改),程序理解引发ConcurrentModificationException,
而不是显示修改后结果,这样可以避免共享资源而引发的潜在问题。
在使用Iterator时候:
对于Collection集合,改变集合的大小会触发ConcurrentModificationException异常;改变集合中元素的内容不会触发异常
对于Map集合,改变集合Map的大小或者元素,均可以正常执行。
/** * Project Name:Spring0725 * File Name:Test5.java * Package Name:work1201.basic * Date:2017年12月1日下午4:16:25 * Copyright (c) 2017, 深圳金融电子结算中心 All Rights Reserved. * */ package work1201.basic; import java.util.ArrayList; import java.util.Iterator; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import org.junit.Test; /** * ClassName:TestIterator <br/> * Function: 测试Collection Map 集合改变对迭代器遍历有无影响 * 在使用Iterator时候,对于Collection集合,改变集合的大小会触发ConcurrentModificationException异常;改变集合中元素的内容不会触发异常 * 对于Map集合,改变集合Map的大小或者元素,均可以正常执行。 * Date: 2017年12月1日 下午4:16:25 <br/> * @author prd-lxw * @version 1.0 * @since JDK 1.7 * @see */ public class TestIterator { @Test public void testDeletCollection(){ ArrayList<String> list = new ArrayList<String>(); for(int i=0;i<20;i++){ list.add(i+""); } Iterator<String> it = list.iterator(); String ss = 10+""; while(it.hasNext()){ if(it.next().equals(ss)){ System.out.println("找到元素:"+ss); // list.remove(ss); //集合大小发生改变 ConcurrentModificationException // list.add(102+""); //集合大小发生改变 ConcurrentModificationException // list.set(19, 211+""); //不会触发异常,因为没有改变Collection集合的大小 } } } @Test public void testIteratorMapEntry(){ ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>(); for(int i=0;i<20;i++){ map.put(i+"", i+""); } Iterator<Entry<String, String>> it = map.entrySet().iterator(); String key = 10+""; while(it.hasNext()){ if(it.next().getKey().equals(key)){ System.out.println("找到元素:"+key); //改变Map map.remove(key); //正常 // map.put(21+"", 21+""); //正常 // map.replace(key, 30+"");//正常 // it.remove(); //正常 System.out.println(map.size()+":"+map.get(key)); } } } @Test public void testIteratorMapKey(){ ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>(); for(int i=0;i<20;i++){ map.put(i+"", i+""); } Iterator<String> it = map.keySet().iterator(); String key = 10+""; while(it.hasNext()){ if(it.next().equals(key)){ System.out.println("找到元素:"+key); //改变Map // map.remove(key); //正常 // map.put(21+"", 21+""); //正常 // map.replace(key, 30+"");//正常 it.remove(); //正常 System.out.println(map.size()+":"+map.get(key)); } } } }
多线程环境下的结果和单测中的结果一致,这里只是为了模拟观察
/** * Project Name:Spring0725 * File Name:IteratorListDelete.java * Package Name:work12.day05 * Date:2017年12月5日下午9:58:53 * Copyright (c) 2017, 深圳金融电子结算中心 All Rights Reserved. * */ package work12.day05; import java.util.ArrayList; import java.util.Iterator; /** * ClassName:IteratorListDelete <br/> * Function: 测试多线程下 改变Collection集合 对迭代器遍历造成的影响 Date: 2017年12月5日 下午9:58:53 <br/> * * @author prd-lxw * @version 1.0 * @since JDK 1.7 * @see */ public class IteratorListDelete { private final ArrayList<String> list; public IteratorListDelete(ArrayList<String> list) { super(); this.list = list; } public ArrayList<String> getList() { return list; } public static void main(String[] args) { ArrayList<String> aList = new ArrayList<String>(); IteratorListDelete tt = new IteratorListDelete(aList); for (int i = 0; i < 100; i++) { tt.getList().add(i + ""); } new Thread(new TraverseList(tt), "子线程").start(); // System.out.println(tt.getList().get(28)); try { Thread.sleep(10); // tt.getList().remove(28+""); // 集合大小发生改变 ConcurrentModificationException tt.getList().add(101 + ""); // 集合大小发生改变 ConcurrentModificationException // tt.getList().set(28, 201+""); //改变集合内容,不会触发异常,因为没有改变Collection集合的大小 } catch (InterruptedException e) { e.printStackTrace(); } } } /** * ClassName: TraverseList <br/> * Function: 线程一直循环遍历collection集合 date: 2017年12月5日 下午10:35:06 <br/> * * @author prd-lxw * @version 1.0 * @since JDK 1.7 */ class TraverseList implements Runnable { private final IteratorListDelete tt; public TraverseList(IteratorListDelete tt) { super(); this.tt = tt; } public void run() { try { Thread.sleep(5); } catch (Exception e) { // TODO: handle exception } while (true) { Iterator<String> it = tt.getList().iterator(); while (it.hasNext()) { System.out.println(Thread.currentThread().getName() + "循环遍历:" + it.next()); } } } }
标签:迭代 logs i++ turn print 线程 res equal .com
原文地址:http://www.cnblogs.com/lixuwu/p/7990141.html