关于Iterator探究和思考

简介:

前两天,一哥们拿着同一个问题连续找了我两次。一开始以为没什么说的东西,后来越研究越觉得有意思,今天闲来无事,写出来跟大家分享。

    问题是这样的:“迭代集合时,Iterator it=c.iterator() 返回的到底接口Iterator的哪个实现类?”。刚开始我随口就是“查查API不就知道了么”,后来证明查API还真就“不知道”。API显示Iterator只有三个实现类(BeanContextSupport.BCSIterator, EventReaderDelegate, Scanner),但是哪一个都不像是跟迭代有关的。后来查源码,发现Iterator设计和实现的精妙之处。

jdk源码 Iterator接口定义如下:

 

1
2
3
4
5
  public  interface  Iterator<E> {
      boolean  hasNext(); //判断容器内是否还有可供访问的元素
      E next(); //返回迭代器刚越过的元素的引用,返回值是Object,需要强制转换成自己需要的类型
      void  remove(); //删除迭代器刚越过的元素
  }

 

我们都知道,其实在编程过程中经常使用的,也只有hasNext()和next()。一般我们都是这么进行迭代:

 

1
2
3
4
5
Iterator it=c.iterator();
while (it.hasNext()){
   Object o=it.next();
   //do something
}

 

不难发现,无论迭代的是List集合还是Set集合,也无论集合底层是采用数组实现的ArrayList、Vector、HashSet,或者是采用链表实现的LinkedList、又或者是采用二叉树实现的TreeSet,统统都是通过统一的方法hasNext()、next()来判断、获取下一个元素,但是具体的内部操作肯定是不一样的,那Iterator是怎么做到的呢?其实,并不是Iterator怎么做到,而是每一个集合类自己分别来进行实现的。下面我以ArrayList为例,跟大家一起分析一下jdk的精妙实现:

    众所周知,ArrayList的内部实现采用数组,所以我们只需要记录相应位置的索引就可以了,其方法的实现也是比较简单的。它通过定义内部类内部类,来实现Iterator接口来实现的,如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  private  class  Itr  implements  Iterator<E> {
   int  cursor =  0 ; //cursor从0开始,表示下一个元素的索引位置
   int  lastRet = - 1 ; //lastRet从-1开始,表示上一个元素的索引位置
   int  expectedModCount = modCount; //记录对集合修改的次数,主要是用于实现ArrayList集合的快速失败机制
   /**
    *hasNext()只需判断当前位置是不是处在最后一个了即可.
    */
   public  boolean  hasNext() {
              return  cursor != size();
   }
   /**
    * next()实现其实也是比较简单的,只要返回cursor索引位置处的元素即可,然后修改cursor、lastRet即可.
    */
   public  E next() {
              checkForComodification(); //主要用来判断集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过.
       try  {
     E next = get(cursor); //从底层实现数组里取得当前元素
     lastRet = cursor++; //lastRet+1
     return  next; //返回当前元素
       catch  (IndexOutOfBoundsException e) {
     checkForComodification();
     throw  new  NoSuchElementException();
       }
   }
   /**
    * 调用ArrayList本身的remove()方法删除lastRet位置元素,然后修改modCount即可.
    */
   public  void  remove() {
       if  (lastRet == - 1 )
        throw  new  IllegalStateException();
              checkForComodification();
       try  {
     AbstractList. this .remove(lastRet); //从底层实现数组里删除上一个元素
     if  (lastRet < cursor)
         cursor--; //由于当前元素要填补到上一个元素的位置去,所以当前元素下标-1
     lastRet = - 1 ;
     expectedModCount = modCount; //把集合的修改次数赋值给expectedModCount
       catch  (IndexOutOfBoundsException e) {
        throw  new  ConcurrentModificationException();
       }
   }
  
   final  void  checkForComodification() {
       if  (modCount != expectedModCount)
    throw  new  ConcurrentModificationException();
   }
    }

 

这就是ArrayList的Iterator接口的实现。有人会问“那岂不是每一个集合类都要提供对Iterator的实现啊?”,对!Iterator只提供方法,你要想使用其进行迭代遍历,就必须提供对它的迭代实现。实际上,LinkedList、Vector、HashSet、TreeSet等集合的Iterator实现也都采用类似的设计思路。

    通过以上探究,我们不难看出,Iterator给我们提供了一种通用的遍历各种集合的方法,它可以把访问逻辑从不同类型的集合类中抽象出来,做到了访问代码和集合本身的解耦,从而避免向客户端暴露集合的内部结构。从此,客户端可以不直接和集合类打交道,它只需要控制Iterator,向它发送“向前”、“向后”、“取当前元素”、“删元素”的命令,就可以间接遍历和操作整个集合,并且这些客户端代码还是可以复用的。其实,这就是java中非常著名的Iterator设计模式。

    书到用时方恨少,事非经过不知难。点滴积累,你就会成为技术上的巨人!





     本文转自NightWolves 51CTO博客,原文链接:http://blog.51cto.com/yangfei520/1731034,如需转载请自行联系原作者




相关文章
|
1天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1055 0
|
10天前
|
人工智能 运维 安全
|
1天前
|
弹性计算 Kubernetes jenkins
如何在 ECS/EKS 集群中有效使用 Jenkins
本文探讨了如何将 Jenkins 与 AWS ECS 和 EKS 集群集成,以构建高效、灵活且具备自动扩缩容能力的 CI/CD 流水线,提升软件交付效率并优化资源成本。
241 0
|
8天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
8天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。
|
9天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
725 23