zoukankan      html  css  js  c++  java
  • Iterator、Iteratable与ListIterator

    • Iteratable:
    public interface Iterable<T> {
    
        Iterator<T> iterator();
    
        default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    
        default Spliterator<T> spliterator() {
            return Spliterators.spliteratorUnknownSize(iterator(), 0);
        }
    }
    
      • Iteratable接口提供了iterator()方法。
      • Collection接口继承了Iteratable,由实现Collection的ArrayList、Hashset等来实现方法。
    • Iterator:

    public interface Iterator<E> {
     
        boolean hasNext();
    
        E next();
    
        default void remove() {
            throw new UnsupportedOperationException("remove");
        }
    
        default void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (hasNext())
                action.accept(next());
        }
    }
    
      • Iterator接口在ArrayList、LinkedList等类中都有内部类实现
      • Iterator接口的不当使用会导致抛出ConcurrentModificationException:
        List<String> famousList = new ArrayList<>();
        famousList.add("Sheldon");
        famousList.add("Sherlock");
        famousList.add("Batman");
        famousList.add("Optimus Prime");
            
        for (String famous :
            famousList) {
            famousList.remove(famous);
        }
    

    上面的代码之所以会抛出ConcurrentModificationException异常的原因:

    • 增强for循环其实在编译生成字节码后会发现,就是转化为通过调用iterator的hasNext()、next()函数来遍历集合,查看ArrayList的iterator的实现代码:
        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;
    
            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();
                }
            }
    
            @Override
            @SuppressWarnings("unchecked")
            public void forEachRemaining(Consumer<? super E> consumer) {
                Objects.requireNonNull(consumer);
                final int size = ArrayList.this.size;
                int i = cursor;
                if (i >= size) {
                    return;
                }
                final Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length) {
                    throw new ConcurrentModificationException();
                }
                while (i != size && modCount == expectedModCount) {
                    consumer.accept((E) elementData[i++]);
                }
                // update once at end of iteration to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
    
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
        }
    

    从以上代码可知,当调用next()函数的时候,会先调用checkForComodification函数来检查集合的modCount与expectedModCount是否相等,若不相等则抛出错误。来到这里就能知道,在使用iterator遍历集合的时候,使用集合的remove、add等函数,就会导致modCount和expectedModCount不一致,从而导致异常抛出。

    • 正确的做法:
        Iterator<String> iterator = famousList.iterator();
        for (;iterator.hasNext();){
            String famous=iterator.next();
            System.out.println(famous);
            if ("Batman".equals(famous)){
                iterator.remove();
                break;
            }
        }
        System.out.println(famousList.size());
    

    或者:

        for (int i = 0; i < famousList.size(); i++) {
            System.out.println(famousList.get(i));
            if ("Batman".equals(famousList.get(i))){
                famousList.remove(famousList.get(i));
                break;
            }
        }
        System.out.println(famousList.size());
    
    • ListIterator:
    public interface ListIterator<E> extends Iterator<E> {
    
        boolean hasNext();
        
        E next();
    
        //判断cursor前是否有元素
        boolean hasPrevious();
    
        //获得cursor前一个元素,并且cursor后退一位
        E previous();
    
        //返回cursor元素的index
        int nextIndex();
    
        //返回cursor前一个元素的index
        int previousIndex();
    
        void remove();
    
        //更新上一次调用next、previous返回的元素,也就是iterator最后一次操作的元素,没有调用next、previous前调用的话会抛出IllegalStateExceptiony异常
        void set(E e);
    
        //向cursor前插入元素
        void add(E e);
    
    }
    
    • ListIterator由实现List接口的集合类通过以下两种方法返回:
        public ListIterator<E> listIterator() {
            return new ListItr(0);
        }
    
        //返回指定cursor位置的listIterator
        public ListIterator<E> listIterator(int index) {
            if (index < 0 || index > size)
                throw new IndexOutOfBoundsException("Index: "+index);
            return new ListItr(index);
        }
    
    

    相比Iterator,多了add、set以及previous等方法。

  • 相关阅读:
    OCP-1Z0-新051-61题版本-20
    OCP-1Z0-新051-61题版本-19
    OCP-1Z0-新051-61题版本-17
    OCP-1Z0-新051-61题版本-18
    OCP-1Z0-新051-61题版本-16
    OCP-1Z0-新051-61题版本-15
    OCP-1Z0-新051-61题版本-14
    OCP-1Z0-新051-61题版本-12
    OCP-1Z0-新051-61题版本-13
    OCP-1Z0-新051-61题版本-11
  • 原文地址:https://www.cnblogs.com/libertycode/p/9906574.html
Copyright © 2011-2022 走看看