迭代输出(Iterator、ListIterator、Enumeration、for-each)fail-fast

迭代器输出

1.迭代输出Iterator----只能从前向后输出----(Collection子类都支持(List和Set集合))
调用Collection集合子类的Iterator方法取得内置的迭代器,使用以下输出格式:

public static void main(String[] args) {
    List<String> list=new ArrayList<>();
    list.add("pick");
    list.add("happy");
    //取得ArrayList的迭代器
    Iterator<String> iterator=list.iterator();
    while(iterator.hasNext())
    {
        System.out.println(iterator.next());
    }
}

2.双向迭代接口ListIterator----------(只有List接口可以,Set接口不支持)
boolean hasNext( ); 判断是否还有元素
E next( ); 取得下一个元素
boolean hasPervious( ); 判断是否有上一个元素
E previous( ):取得上一个元素

public static void main(String[] args) {
    List<String> list=new ArrayList<>();
    list.add("pick");
    list.add("happy");
    //取得ArrayList的迭代器
    ListIterator<String> listiterator=list.listIterator();
    while(listiterator.hasNext())
    {
        System.out.println(listiterator.next());  //pick  happy
    }

    while (listiterator.hasPrevious())
    {
        System.out.println(listiterator.previous());//happy pick
    }
}

注意:要想从后向前遍历,首先至少要从前向后遍历一次才可以使用。
3.Enumeration枚举输出----只有Vector类支持
public boolean hasMoreElements() :判断是否有下一个元素
public E nextElements():取得下一个元素

//Enumeration
public class Iterator1 {
    public static void main(String[] args) {
        Vector<String> vector=new Vector<>();
        vector.add("pick");
        vector.add("happy");
        //取得ArrayList的迭代器
        Enumeration<String> enumeration=vector.elements();
        while(enumeration.hasMoreElements())
        {
            System.out.println(enumeration.nextElement());  //pick  happy
        }
    }
}

4.for-each输出(所有子类都满足)
能使用for-each输出的本质是各个集合类都内置了迭代器
在for-each添加或删除元素会有并发修改异常

fail-fast

产生ConcurrentModificationException异常:

public static void main(String[] args) {
    List<String> list=new ArrayList<>();
    Collections.addAll(list,"A","B","C","D","B","a");
    Iterator<String> iterator=list.iterator();
    while(iterator.hasNext())
    {
        String str=iterator.next();
        if(str.equals("B")) {
            list.remove("B");  //使用list.remove发生异常
            continue;
        }
        System.out.println(str);
    }
}

ConcurrentModificationException异常发生在Collection集合使用迭代器遍历时,使用了集合类提供的修改集合内容方法报错。而如果使用Iterator迭代器的remove( )不会出现此错误。

public class Iterator1 {
    public static void main(String[] args) {
        List<String> list=new ArrayList<>();
        Collections.addAll(list,"A","B","C","D","B","a");
        Iterator<String> iterator=list.iterator();
        while(iterator.hasNext())
        {
            String str=iterator.next();
            if(str.equals("B")) {
                iterator.remove();  //使用list.remove发生异常
                continue;
            }
            System.out.println(str); // A C D a
        }
    }
}

ConcurrentModificationException异常产生分析:

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

Collection集合中的modCount表示当前集合修改的次数
expectedModCount 是迭代器中记录当前集合的修改次数
当取得集合迭代器(即调用List.Iterator( )),expectedModCount =modCount,即迭代器是当前集合的一个副本。
在集合的add和remove方法中会将modCount++,在迭代器遍历时next( )时会判断expectedModCount 、modCount是否相等,不相等将会抛异常ConcurrentModificationException。

public static void main(String[] args) {
    List<String> list=new ArrayList<>();
    Collections.addAll(list,"A","B","C","D","B","a");
    //此时modCount=6
    Iterator<String> iterator=list.iterator();
    //此时调用list.iterator(),取得集合迭代器,expectedModCount =modCount=6
    while(iterator.hasNext())
    {
     
         //下一次循环调next方法,会调用checkForComodification判断副本的         expectedModCount 和集合的modCount是否相等,
           // 不相等抛异常
        String str=iterator.next();
        if(str.equals("B")) {
            list.remove("B"); //使用list.remove发生异常
            //调用list.remove(),modCount=7,然后进行下一次循环
            continue;
        }
        System.out.println(str); // A C D a
    }
}

快速失败策略保证了所有用户在进行迭代遍历集合时,拿到的数据一定是最新的数据(避免“脏读”产生)。
在这里脏读是:假如线程1在遍历迭代器中元素,线程2在修改元素,那么线程1读到的数据就有问题,即是脏读,但是抛出异常后,线程1就知道遍历的元素有问题。
抛异常尽量保证了在多线程情况下数据不会产生脏读,即若有线程并发修改集合结构时,向同时在遍历此集合的线程发出一个异常,通知其集合数据已经修改。

产生ConcurrentModificationException异常的类有?
ArrayList Vector (尽管是synchronized) LinkedList HashMap Hashtable

为什么调用迭代器的remove可以?
因为会把副本的expectedModCount更新到最新值。
fail-safe
不产生 ConcurrentModificationException异常
juc包下所有线程安全集合(CopyOnWriteArrayList ConcurrentHashMapt)
总结:在迭代器遍历时,不要修改集合内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值