码迷,mamicode.com
首页 > 其他好文 > 详细

迭代器Iterator

时间:2017-12-06 00:53:35      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:迭代   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的大小或者元素,均可以正常执行。

集合Collection 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());
            }
        }

    }

}

 

迭代器Iterator

标签:迭代   logs   i++   turn   print   线程   res   equal   .com   

原文地址:http://www.cnblogs.com/lixuwu/p/7990141.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!