美文网首页
集合--迭代器

集合--迭代器

作者: sjandroid | 来源:发表于2018-08-09 19:31 被阅读0次

    目录

    • Iterable
    • Iterator
    • ListIterator
    • Spliterator

    java主要容器类图(除Map外,因为Map并未实现Collection接口),从图中可以知道Collection接口实现了Iterable接口。
    那Iterable是干嘛的呢??

    整体类图.jpg

    Iterable

    说明

    该接口是从JDK1.5添加的,目的是 可以通过foreach语句遍历那么实现了该接口的类中的数据元素

    方法

    iterator()

    说明:返回一个迭代器实例。

    使用

    • 遍历集合类中的数据
        private static void test_2(){
            List<String> list = new ArrayList<>();
            list.add("1");
            list.add("2");
            list.add("3");
    
            //while循环(显示调用Iterator)
            //Iterator<String> iterator = list.iterator();
            //while(iterator.hasNext()){
            //    System.out.println(iterator.next());
            //}
    
            //普通for循环(显示调用Iterator)
            //for(Iterator<String> iterator2 = list.iterator(); iterator.hasNext();){
            //    System.out.println(iterator.next());
            //}
    
            //for-each遍历(隐式调用Iterator)
            //for-each语法内部会调用Collection中的iterator()生成一个迭代器实例。
            //其内部会调用iterator的hasNext()判断是否还有更多元素。调用next()方法,把返回的数据赋值为str。
            for(String str : list){
                System.out.println(str);
            }
        }
    
    • 遍历自定义类中存储的数据元素
        private static void test_1(){
            Test<String> test = new Test<>(new String[]{"Who Are You?", "I am 雷锋."});
    
            for(String str : test){
                System.out.println(str);
            }
        }
    
        /**
         * 具体的Iterable实现类
         */
        private static class Test<T> implements Iterable<T>{
            private T[] array;
    
            public Test(T[] array) {
                this.array = array;
            }
    
            @Override
            public Iterator<T> iterator() {
                return new TestIterator<>(array);
            }
    
            /**
             * 自定义迭代器
             */
            private static class TestIterator<E> implements Iterator<E>{
    
                private E[] array;
                private int index;
    
                public TestIterator(E[] array) {
                    this.array = array;
                }
    
                @Override
                public boolean hasNext() {
                    return this.index < this.array.length;
                }
    
                @Override
                public E next() {
                    return this.array[this.index++];
                }
            }
        }
    

    log

    Who Are You?
    I am 雷锋.
    

    接下来看看Iterator是什么,以及它的作用是干嘛的吧。


    Iterator

    说明

    方法:
    hasNext():

    说明:是否还有更多元素。

    next():

    说明:如果还有元素的话,则返回下一个元素。

    remove():

    说明:
    1:从底层集合中移除此迭代器返回的最后一个元素。
    2:调用此方法之前,需要调用next(),且next()方法调用后只可以调用该方法一次。(多次调用remove()会抛出IllegalStateException)

    验证

    在调用next()前调用remove()

        private static void test_3(){
            List<String> list = new ArrayList<>();
            list.add("1");
            list.add("2");
            list.add("3");
    
            for(Iterator<String> iterator = list.iterator(); iterator.hasNext();){
                iterator.remove();
                System.out.println(iterator.next());
            }
        }
    

    log

    Exception in thread "main" java.lang.IllegalStateException
        at java.util.LinkedList$ListItr.remove(LinkedList.java:923)
        at com.iterator.Iterable_Foreach_Test_1.test_3(Iterable_Foreach_Test_1.java:63)
        at com.iterator.Iterable_Foreach_Test_1.main(Iterable_Foreach_Test_1.java:20)
    

    调用next()后,多次调用remove()

        private static void test_3(){
            List<String> list = new ArrayList<>();
            list.add("1");
            list.add("2");
            list.add("3");
    
            for(Iterator<String> iterator = list.iterator(); iterator.hasNext();){
                System.out.println(iterator.next());
                iterator.remove();
                iterator.remove();
            }
        }
    

    log

    1
    Exception in thread "main" java.lang.IllegalStateException
        at java.util.ArrayList$Itr.remove(ArrayList.java:872)
        at com.iterator.Iterable_Foreach_Test_1.test_3(Iterable_Foreach_Test_1.java:65)
        at com.iterator.Iterable_Foreach_Test_1.main(Iterable_Foreach_Test_1.java:20)
    

    通过上述对Iterator的说明基本上在使用的时候做到了心中有数,接下来从源码入手,看一看Iterator的内部实现。


    源码分析

    ArrayList类结构图.png

    接下来我们将从以下几点分析Collection中的迭代器实现。

    • 什么是fail-fast
    • AbstractList中的Iteraror实现
    • ArrayList中的Iterator相较于AbstractList中的Iterator做了哪些优化
    什么是fail-fast
    fail-fast机制介绍:
    • 说明:
      fail-fast是一种 错误 机制,当检测到 容器 类的结构被进行了 不正确修改之后,则会抛出ConcurrentModificationException。
    • 触发:
      在使用迭代器时对 容器 类中的数据元素遍历,添加,删除,修改时。
    • 作用:
      用于提醒 容器 类的结构被进行了 不正确修改
    • 如何检测(检测依据):
      迭代器中会保存容器类中modCount的一个副本,当利用迭代器进行遍历,添加,删除,修改操作时,会检测迭代器中的modCount与容器类中的modCount值是否一致,如果不一致则会抛出ConcurrentModificationException,此时fail-fast事件就产生了。
    注意:
    • modCount:该值是用于记录 AbstractList结构被修改的次数。那么什么操作会引起AbstractList的结构发生改变呢?
    • 具体的例如List的add操作,remove操作等,这些方法都会对List的存储数据的列表大小发生更改。详细请查看 集合--ArrayList--基本方法使用说明 中关于subList()方法的介绍。

    AbstractList中的Iteraror实现
        private class Itr implements Iterator<E> {
            /**
             * Index of element to be returned by subsequent call to next.
             * 记录要返回的下一个元素的索引。
             */
            int cursor = 0;
    
            /**
             * Index of element returned by most recent call to next or
             * previous.  Reset to -1 if this element is deleted by a call
             * to remove.
             * 1:调用previous()后,记录的是此元素之后的一个元素索引。 
             * 2:调用next()后,记录的是此元素之前的一个元素索引。
             * 3:如果调用 remove()删除此元素,则该值重置为-1。
             * 
             * 总结:
             * 1:用于记录当前元素之前或者之后一个元素在列表中的位置。
             * 2:调用next()/previous()后此值才会大于-1。调用remove()后此值被重置为-1。
             */
            int lastRet = -1;
    
            /**
             * The modCount value that the iterator believes that the backing
             * List should have.  If this expectation is violated, the iterator
             * has detected concurrent modification.
             * 1:用于同步AbstractList的modCount属性值。
             * 2:如果检测到该值与AbstractList的modCount值不相等的话则会抛出
             * ConcurrentModificationException。
             */
            int expectedModCount = modCount;
    
            //查看是否还有后续元素
            public boolean hasNext() {
                return cursor != size();
            }
            
            //返回列表中的下一个元素
            public E next() {
                checkForComodification();
                try {
                    int i = cursor;
                    E next = get(i); 
                    lastRet = i; 
                    cursor = i + 1; 
                    return next;
                } catch (IndexOutOfBoundsException e) {
                    checkForComodification();
                    throw new NoSuchElementException();
                }
            }
            
            //从列表中移除调用next()后新近返回的元素
            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();
    
                try {
                    AbstractList.this.remove(lastRet);
                    if (lastRet < cursor)
                        cursor--;
                    lastRet = -1;
                    expectedModCount = modCount; //调用remove操作List的结构发生了更
    改,此时需要同步modCount(remove会使modCount+1代表对列表结构进行了一次
    修改)
                } catch (IndexOutOfBoundsException e) {
                    throw new ConcurrentModificationException();
                }
            }
            
            //检查AbstractList是否发生了并发操作对AbstractList结构造成了错误的修改。
            //比较Iterator的modCount是否与外部类中的modCount值一致
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
        }
    

    参考:
    https://www.jb51.net/article/92127.htm
    https://blog.csdn.net/u011518120/article/details/51932040
    http://www.cnblogs.com/skywang12345/p/3308762.html

    相关文章

      网友评论

          本文标题:集合--迭代器

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