zoukankan      html  css  js  c++  java
  • JAVA基础——集合Iterator迭代器的实现

    一、迭代器概述

      1、什么是迭代器?

      在Java中,有很多的数据容器,对于这些的操作有很多的共性。Java采用了迭代器来为各种容器提供了公共的操作接口。这样使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。

      在Iterator接口中定义了三个方法:

      

      2、迭代器使用

    复制代码
        public static void main(String[] args)
        {
            List<String> list=new ArrayList<>();
            list.add("abc");
            list.add("edf");
            list.add("ghi");
            for(Iterator<String> it=list.iterator();it.hasNext();)
            {
                System.out.println(it.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;
           ...
        }
    复制代码

      在ArrayList内部定义了一个内部类Itr,该类实现了Iterator接口。

      在Itr中,有三个变量分别是

      cursor:表示下一个元素的索引位置

      lastRet:表示上一个元素的索引位置

      expectModCount:预期被修改的次数

      下面看一下Itr类实现了Iterator接口的三个方法:

     public boolean hasNext() 
     {
         return cursor != size;//当cursor不等于size时,表示仍有索引元素
     }
    复制代码
         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];
        }
    复制代码

      在next()方法中有一个checkForComodification()方法,其实现为:

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

      可以看到,该函数是用来判断集合的修改次数是否合法。

      在集合内部维护一个字段modCount用于记录集合被修改的次数,每当集合内部结构发生变化(add,remove,set)时,modCount+1。

      在迭代器内部也维护一个字段expectedModCount,同样记录当前集合修改的次数,初始化为集合的modCount值。当我们在调用Iterator进行遍历操作时,如果有其他线程修改list会出现modCount!=expectedModCount的情况,就会报并发修改异常java.util.ConcurrentModificationException。下面为示例代码:

    复制代码
       public static void main(String[] args)
        {
             ArrayList<String> aList=new ArrayList<String>();
             aList.add("bbc");
             aList.add("abc");
             aList.add("ysc");
             aList.add("saa");
             System.out.println("移除前:"+aList);
       
             Iterator<String> it=aList.iterator();
             while(it.hasNext())
             {
                 if("abc".equals(it.next()))
                 {
                    aList.remove("abc");          
                 }
             }
             System.out.println("移除后:"+aList);
      }            
    复制代码

      

      上面的代码中,如果我们只使用迭代器来进行删除,则不会出现并发修改异常错误。

    复制代码
      public static void main(String[] args)
        {
           ArrayList<String> aList=new ArrayList<String>();
             aList.add("bbc");
             aList.add("abc");
             aList.add("ysc");
             aList.add("saa");
             System.out.println("移除前:"+aList);
             
             Iterator<String> it=aList.iterator();
             while(it.hasNext())
             {
                if("abc".equals(it.next()))
                {
                  it.remove();
                }
             }
             System.out.println("移除后:"+aList);
      }
    复制代码

      

    复制代码
         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();
                }
         }
    复制代码

      在执行remove操作时,同样先执行checkForComodification(),然后会执行ArrayList的remove()方法,该方法会将modCount值加1,这里我们将expectedModCount=modCount,使之保持统一。

    三、ListIterator

      上面可以看到,Iterator只提供了删除元素的方法remove,如果我们想要在遍历的时候添加元素怎么办?

      ListIterator接口继承了Iterator接口,它允许程序员按照任一方向遍历列表,迭代期间修改列表,并获得迭代器在列表中的当前位置。

      ListIterator接口定义了下面几个方法:

      

      下面使用ListIterator来对list进行边遍历边添加元素操作:

    复制代码
        public static void main(String[] args)
        {
            ArrayList<String> aList = new ArrayList<String>();
            aList.add("bbc");
            aList.add("abc");
            aList.add("ysc");
            aList.add("saa");
            System.out.println("移除前:" + aList);
            ListIterator<String> listIt = aList.listIterator();
            while (listIt.hasNext())
            {
                if ("abc".equals(listIt.next()))
                {
                    listIt.add("haha");
                }
            }
            System.out.println("移除后:" + aList);
        }
    复制代码

      

  • 相关阅读:
    【第40套模拟题】【noip2011_mayan】解题报告【map】【数论】【dfs】
    【模拟题(63550802...)】解题报告【贪心】【拓扑排序】【找规律】【树相关】
    【模拟题(电子科大MaxKU)】解题报告【树形问题】【矩阵乘法】【快速幂】【数论】
    IMemoryBufferReference and IMemoryBufferByteAccess
    SoftwareBitmap and BitmapEncoder in Windows.Graphics.Imaging Namespace
    Windows UPnP APIs
    编译Android技术总结
    Windows函数转发器
    Two Ways in Delphi to Get IP Address on Android
    Delphi Call getifaddrs and freeifaddrs on Android
  • 原文地址:https://www.cnblogs.com/huan-guo/p/8474580.html
Copyright © 2011-2022 走看看