美文网首页
java迭代器

java迭代器

作者: remoteMountain | 来源:发表于2019-05-09 14:37 被阅读0次

    与java迭代器相关的类的继承关系

    java迭代器继承体系.png

    ArrayList中的迭代器

    其实获取ArrayList的迭代器是一个Iterator的实现-Itr,定义如下。

    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
       public Iterator<E> iterator() {
            return new Itr();
        }
    
    }
    
    

    ArrayList中定义了一个内部类Itr,实现了ListIterator接口。

    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;
    
            Itr() {}
    
            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();
            }
        }
    

    迭代的时候操作原始集合

    public static void main(String[] args) {
            Collection<String> list = new ArrayList<String>();
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("d");
            list.add("e");
    
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()){
                if (iterator.next() == "a"){
                    list.remove("a");
                }
            }
        }
    

    上述代码的执行结果

    Exception in thread "main" java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
        at java.util.ArrayList$Itr.next(ArrayList.java:859)
        at org.learnspring.service.v2.PetStoreService.main(PetStoreService.java:55)
    

    报错的原因分析如下:
    迭代器的next方法,每次都会判断两个变量的值是否相等,不相等就会报ConcurrentModificationException。其中的两个变量分别是定义在Itr中的expectedModCount和定义在ArrayList中的modCount。而判断的方法是定义在ItrcheckForComodification方法。

    如何在迭代器迭代的时候操作原始集合

    我们可以使用迭代器自己的remove方法来删除集合中被扫描到的元素。

    public static void main(String[] args) {
            Collection<String> list = new ArrayList<String>();
            list.add("a");
            list.add("b");
            list.add("c");
            list.add("d");
            list.add("e");
    
            Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()){
                if (iterator.next() == "a"){
                    iterator.remove();
                }
            }
            System.out.println(list);
        }
    

    执行结果

    [b, c, d, e]
    

    我们分析迭代器中的remove方法,发现它内部是调用ArrayListremove方法来移除元素的,ArrayList.this.remove(lastRet);

    那么,为什么这样就不会报错呢?
    因为,每次remove之后都会将迭代器的指针向前推移一位,保证了迭代器能够扫描到集合中所有的元素。
    同时确保两个变量的值相等,通过赋值的操作来保证。

    相关文章

      网友评论

          本文标题:java迭代器

          本文链接:https://www.haomeiwen.com/subject/nsewoqtx.html