zoukankan      html  css  js  c++  java
  • Java容器类源码分析之Iterator与ListIterator迭代器(基于JDK8)

    一、基本概念

      

        迭代器是一个对象,也是一种设计模式,Java有两个用来实实现迭代器的接口,分别是Iterator接口和继承自Iterator的ListIterator接口。实现迭代器接口的类的对象有遍历集合对象,选择集合中的元素和删除集合中元素的方法。而在使用它时不必知道该集合对象底层的结构。Java类库中实现Iterator接口的迭代器只能正向遍历集合中的元素,而实现ListIterator接口的迭代器不仅能够正向遍历,还能够反向遍历集合中的元素。

    二、源码分析

    2.1、Iterator接口与ListIterator接口的继承与实现

    图2.1  Java迭代器类的继承与接口实现(部分)

     

        ListIterator接口继承了Iterator接口。在AbstractList、ArrayList和Vector这三个类中的内部类ListItr实现了ListIterator接口,这三个类的内部类ListItr又分别继承了在这三个类中实现了Iterator接口的内部类Itr。实现ListIterator的类还有LinkedList的内部类ListItr。实现Iterator的类还有LinkedList的内部类DescendingIterator,HashMap的内部类EntryIterator,KeyIterator,ValueIterator,以及TreeMap的内部类PrivateEntryIterator等。

    2.2、迭代器接口方法

           

            1)迭代器的向前移动与向后移动图解

     

     

             2)Iterator接口方法

     

    package java.util;
    
    import java.util.function.Consumer;
    
    public interface Iterator<E> {
    
        boolean hasNext();
    
    /*   在Java中,这个方法的具体实现一般用来在遍历容器时,调用该方法使迭代器向前移动一位,来检测集合中是否还有下一个元素,还有下一个元素返回true,否则返回false*/
     
        E next();
    
    /*   实现这个方法,在遍历容器时,调用该方法将迭代器向前移动一位,并将迭代器越过的一个元素作为方法的返回值。该方法用来返回集合中下一个元素。
    在调用next()方法前,先调用hasNext()方法判断集合中是否还有下一个元素
    */

    default void remove() { throw new UnsupportedOperationException("remove"); }

    /* 实现这个方法,用来删除在迭代器调用next()方法迭代器越过的一个元素*/

    default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); }

    /* 实现这个方法来顺序遍历容器中的每个元素,用来实现集合类的ForEach遍历操作*/
    }

     

           3)ListIterator接口方法

     

     

    package java.util;
    
    public interface ListIterator<E> extends Iterator<E> {
      
        boolean hasNext();//同Iterator接口,用来检测迭代器前面是否还有元素
       
        E next();

    // 同Iterator接口,使迭代器向前移动一位,获得迭代器越过的下一个元素 boolean hasPrevious();

    // 实现这个方法来检测当前迭代器位置后面是否有元素,用于反向遍历 E previous(); /* 实现这个方法,将迭代器向后移动一位,并将迭代器越过的后面的一个元素作为方法返回值,在调用该方法前需要调用hasPrevious方法来判断迭代器前是否有元素 */ int nextIndex();//实现该方法获取迭代器前面一个元素的索引 int previousIndex();//实现该方法获取迭代器后面一个元素的索引 void remove(); /* 实现该方法,用来删除迭代器调用next()方法或调用previous()方法时迭代器越过的一个元素 */ void set(E e);//实现该方法在迭代器遍历时修改元素 void add(E e);//实现该方法在迭代器遍历时添加元素 }

     

     

     

    2.3、容器类与迭代器的关系

     

           1)Iterator接口。阅读源码可知,Collectiion接口实现了Iterable接口,Iterable有一个返回一个Iterator<T>对象的iterator()方法,所以继承和实现了Collection接口的所有容器类及其子类和实现类都有一个返回Iterator对象的的iterator()方法。Java中有很多容器类中都设计有实现了Iterator接口的内部类,如ArrayList和LinkedList等类。HashMap和TreeMap类中也包含有实现了Iterator的内部类,来对Map中的KeySet、Value和EntrySet进行迭代。Iterable接口的源代码如下:

    public interface Iterable<T> {
    
        Iterator<T> iterator();//实现这个方法,该方法返回一个Iterator迭代器对象。
    default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }//实现这个方法来对容器进行ForEach遍历 default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } }

          

            2)ListIterator接口。查看源码可以发现,List接口中有两个返回ListIterator<T>对象的方法,如下。List接口下的的ArrayList和LinkedList都有返回ListIterator对象的方法。

     

    ListIterator<E> listIterator();//实现这个方法,该方法返回一个ListIterator迭代器对象,迭代器初始化后,一般迭代器位于在容器第一个元素后面。
    
    ListIterator<E> listIterator(int index);//实现这个方法,返回一个指定了开始遍历容器时迭代器初始位置的ListIterator迭代器对象

     

    • ArrayList类设计有实现了ListIterator接口的内部类ListItr(不过ArrayList的listIterator(final int index)方法并未使用这个内部类,而是在方法中又设计了一个ListIterator匿名内部类作为方法返回值,可以发现ArrayList的Iterator()方法也是调用了这个方法来构建迭代器对象)。ArrayList类中部分有关源码如下
      private class ListItr extends Itr implements ListIterator<E> {
            ListItr(int index) {
                super();
                cursor = index;
            }
      public Iterator<E> iterator() {
                return listIterator();
            }
    
            public ListIterator<E> listIterator(final int index) {
                checkForComodification();
                rangeCheckForAdd(index);
                final int offset = this.offset;
    
                return new ListIterator<E>() {//返回了一个ListIterator匿名内部类
                    int cursor = index;
                    int lastRet = -1;
                    int expectedModCount = ArrayList.this.modCount;
    
                    public boolean hasNext() {
                        return cursor != SubList.this.size;
                    }

         

    •   LinkedList类也有一个内部类ListItr实现了ListIterator接口,LinkedList的listIterator()方法返回了这个内部类的实例。LinkedList中部分有关源码如下
        public ListIterator<E> listIterator(int index) {
            checkPositionIndex(index);
            return new ListItr(index);
        }
    
        private class ListItr implements ListIterator<E> {

    (小官原创,若有谬误,望各位前辈批评指正)

     

     

     

     

     

     

     

     

  • 相关阅读:
    在scrapy的spiders文件中设置请求时间间隔
    Python中map和reduce函数
    正则表达式
    eslint下的rules一些规则(转:备用)
    谷歌云设置xshell登录
    (过期)活动赠送的国外云服务器VPS【速度极慢,适合小白练手】
    关于服务器的那些事~~~
    call()和appy()的区别及常用场景
    javascript中使用this关键字的大总结
    懵懵懂懂、迷迷糊糊
  • 原文地址:https://www.cnblogs.com/jianguan/p/10680821.html
Copyright © 2011-2022 走看看