java提高篇(三十)-----Iterator

来源:互联网 发布:移动通信网络优化技术 编辑:程序博客网 时间:2024/04/25 05:53
迭代对于我们搞Java的来说绝对不陌生。我们常常使用JDK提供的迭代接口进行Java集合的迭代。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. Iterator iterator = list.iterator();  
  2.         while(iterator.hasNext()){  
  3.             String string = iterator.next();  
  4.             //do something  
  5.         }  

        迭代其实我们可以简单地理解为遍历,是一个标准化遍历各类容器里面的所有对象的方法类,它是一个很典型的设计模式。Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。 在没有迭代器时我们都是这么进行处理的。如下:

        对于数组我们是使用下标来进行处理的:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. int[] arrays = new int[10];  
  2. for(int i = 0 ; i < arrays.length ; i++){  
  3.        int a = arrays[i];  
  4.        //do something  
  5.    }  

        对于ArrayList是这么处理的:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. List<String> list = new ArrayList<String>();  
  2.    for(int i = 0 ; i < list.size() ;  i++){  
  3.       String string = list.get(i);  
  4.       //do something  
  5.    }  

        对于这两种方式,我们总是都事先知道集合的内部结构,访问代码和集合本身是紧密耦合的,无法将访问逻辑从集合类和客户端代码中分离出来。同时每一种集合对应一种遍历方法,客户端代码无法复用。 在实际应用中如何需要将上面将两个集合进行整合是相当麻烦的。所以为了解决以上问题,Iterator模式腾空出世,它总是用同一种逻辑来遍历集合。使得客户端自身不需要来维护集合的内部结构,所有的内部状态都由Iterator来维护。客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合。

        上面只是对Iterator模式进行简单的说明,下面我们看看Java中Iterator接口,看他是如何来进行实现的。

一、java.util.Iterator

        在Java中Iterator为一个接口,它只提供了迭代了基本规则,在JDK中他是这样定义的:对 collection 进行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。迭代器与枚举有两点不同:

        1、迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的 collection 移除元素。

        2、方法名称得到了改进。

        其接口定义如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public interface Iterator {  
  2.   boolean hasNext();  
  3.   Object next();  
  4.   void remove();  
  5. }  

        其中:

        Object next():返回迭代器刚越过的元素的引用,返回值是Object,需要强制转换成自己需要的类型

        boolean hasNext():判断容器内是否还有可供访问的元素

        void remove():删除迭代器刚越过的元素

        对于我们而言,我们只一般只需使用next()、hasNext()两个方法即可完成迭代。如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. for(Iterator it = c.iterator(); it.hasNext(); ) {  
  2.   Object o = it.next();  
  3.    //do something  
  4. }  

        前面阐述了Iterator有一个很大的优点,就是我们不必知道集合的内部结果,集合的内部结构、状态由Iterator来维持,通过统一的方法hasNext()、next()来判断、获取下一个元素,至于具体的内部实现我们就不用关心了。但是作为一个合格的程序员我们非常有必要来弄清楚Iterator的实现。下面就ArrayList的源码进行分析分析。

二、各个集合的Iterator的实现

        下面就ArrayList的Iterator实现来分析,其实如果我们理解了ArrayList、Hashset、TreeSet的数据结构,内部实现,对于他们是如何实现Iterator也会胸有成竹的。因为ArrayList的内部实现采用数组,所以我们只需要记录相应位置的索引即可,其方法的实现比较简单。

2.1、ArrayList的Iterator实现

        在ArrayList内部首先是定义一个内部类Itr,该内部类实现Iterator接口,如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. private class Itr implements Iterator<E> {  
  2.     //do something  
  3. }  

        而ArrayList的iterator()方法实现:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public Iterator<E> iterator() {  
  2.         return new Itr();  
  3.     }  

        所以通过使用ArrayList.iterator()方法返回的是Itr()内部类,所以现在我们需要关心的就是Itr()内部类的实现:

在Itr内部定义了三个int型的变量:cursor、lastRet、expectedModCount。其中cursor表示下一个元素的索引位置,lastRet表示上一个元素的索引位置

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. int cursor;               
  2. int lastRet = -1;       
  3. int expectedModCount = modCount;  

        从cursor、lastRet定义可以看出,lastRet一直比cursor少一所以hasNext()实现方法异常简单,只需要判断cursor和lastRet是否相等即可。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public boolean hasNext() {  
  2.     return cursor != size;  
  3. }  

        对于next()实现其实也是比较简单的,只要返回cursor索引位置处的元素即可,然后修改cursor、lastRet即可,

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public E next() {  
  2.             checkForComodification();  
  3.             int i = cursor;    //记录索引位置  
  4.             if (i >= size)    //如果获取元素大于集合元素个数,则抛出异常  
  5.                 throw new NoSuchElementException();  
  6.             Object[] elementData = ArrayList.this.elementData;  
  7.             if (i >= elementData.length)  
  8.                 throw new ConcurrentModificationException();  
  9.             cursor = i + 1;      //cursor + 1  
  10.             return (E) elementData[lastRet = i];  //lastRet + 1 且返回cursor处元素  
  11.         }  

        checkForComodification()主要用来判断集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过。在java提高篇(二一)-----ArrayList中已经阐述了。modCount用于记录ArrayList集合的修改次数,初始化为0,,每当集合被修改一次(结构上面的修改,内部update不算),如add、remove等方法,modCount + 1,所以如果modCount不变,则表示集合内容没有被修改。该机制主要是用于实现ArrayList集合的快速失败机制,在Java的集合中,较大一部分集合是存在快速失败机制的,这里就不多说,后面会讲到。所以要保证在遍历过程中不出错误,我们就应该保证在遍历过程中不会对集合产生结构上的修改(当然remove方法除外),出现了异常错误,我们就应该认真检查程序是否出错而不是catch后不做处理。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. final void checkForComodification() {  
  2.      if (modCount != expectedModCount)  
  3.          throw new ConcurrentModificationException();  
  4.  }  

        对于remove()方法的是实现,它是调用ArrayList本身的remove()方法删除lastRet位置元素,然后修改modCount即可。

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public void remove() {  
  2.             if (lastRet < 0)  
  3.                 throw new IllegalStateException();  
  4.             checkForComodification();  
  5.   
  6.             try {  
  7.                 ArrayList.this.remove(lastRet);  
  8.                 cursor = lastRet;  
  9.                 lastRet = -1;  
  10.                 expectedModCount = modCount;  
  11.             } catch (IndexOutOfBoundsException ex) {  
  12.                 throw new ConcurrentModificationException();  
  13.             }  
  14.         }  

        这里就对ArrayList的Iterator实现讲解到这里,对于Hashset、TreeSet等集合的Iterator实现,各位如果感兴趣可以继续研究,个人认为在研究这些集合的源码之前,有必要对该集合的数据结构有清晰的认识,这样会达到事半功倍的效果!!!!

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信绑定银行卡手机号码换了怎么办 银行卡网银登录输错密码锁了怎么办 中行信用卡主付卡的付卡怎么办停 在苏宁网购的移动空调要退货怎么办 单位发的购物卡掉了怎么办 支付宝ofo退押金后余额怎么办 e招贷分期多还了怎么办 别人用我的手机号贷款不还怎么办 电脑文件夹怎么设密码忘记了怎么办 苹果手机id有分机和主机怎么办 绝地求生号被盗了邮箱被改了怎么办 微信邮箱怎么接收不到验证码怎么办 要申请一个特定的qq邮箱号怎么办 中银e贷额度为0怎么办 中银e贷被冻结了怎么办 中国银行e贷款填错了被拒怎么办 中银e贷逾期2天怎么办 大学生助学贷款网站密码忘了怎么办 乳晕毛囊挤压捏起来有小硬节怎么办 手机版模拟人生孕妇任务卡死怎么办 百度网盘的表格没保存怎么办 爱奇艺买的会员不小心删了怎么办 多次举报和拉黑克隆不了好友怎么办 货车把货拉到货主不付钱怎么办 中国银行网银公司用户名忘了怎么办 伟星管网站查不到电水管图纸怎么办 我的耕地己确权被他人侵权怎么办 掌上川电登录密码忘记了怎么办 华为商城不小心点了确认收货怎么办 买的认证服务号没有微信支付怎么办 手机微信里的外网链接打不开怎么办 微信违规无法加入群聊怎么办 苹果手机微信储存空间不足怎么办 拼多多砍价砍不到0元怎么办 妻子婚内出轨我的熟人怎么办 父亲怀疑母亲有外遇作为儿子怎么办 老婆出轨我总心理过不去坎该怎么办 失业人员离培训机构远了怎么办 遇到申请假冒商品的仅退款怎么办 微信被骗什么消息都不知道怎么办 微信用手机登录显示未注册怎么办