Iterable

Iterable :故名思议,实现了这个接口的集合对象支持迭代,是可迭代的。

一个集合对象要表明自己支持迭代,能有使用foreach语句的特权,就必须实现Iterable接口,表明我是可迭代的!然而实现Iterable接口,就必需为foreach语句提供一个迭代器。
这个迭代器是用接口定义的 iterator方法提供的。也就是iterator方法需要返回一个Iterator对象。
  1. //Iterable JDK源码
  2. //可以通过成员内部类,方法内部类,甚至匿名内部类去实现Iterator
  3. public interface Iterable<T>
  4. {
  5. Iterator<T> iterator();
  6. }

Iterator

包含3个方法: hasNext ,  next , remove。remove按需求实现,一般它很少用到,以至于Eclipse接口方法自动补全时,都忽略了remove放方法。

1、hasNext()方法,判断是否有下一个元素。每次在迭代前   ,先调用hasNext()探测是否迭代到终点(本次还能再迭代吗?)。
2、next()方法,返回当前元素,并后移游标cursor来指向下一个元素。注意:next()方法返回的是当前元素,而不是下一个元素,它只是在返回当前元素后指向下一个元素
3、remove()方法用来删除最近一次已经迭代出的元素(注意,要想在迭代过程中删除元素,不要在迭代中直接使用List实例的remove方法,而要使用迭代器实例的remove方法) 
4、 迭代出的元素是原集合中元素引用的拷贝(重要)
5、配合foreach使用
  1. //Iterator接口的JDK源码,注释为整理建议使用Iterator的正确姿势
  2.  
  3. public interface Iterator<E> {
  4.  
  5. boolean hasNext(); //每次next之前,先调用此方法探测是否迭代到终点
  6. E next(); //返回当前迭代元素 ,同时,迭代游标后移
  7.  
  8. /*删除最近一次已近迭代出出去的那个元素。
  9. 只有当next执行完后,才能调用remove函数。
  10. 比如你要删除第一个元素,不能直接调用 remove() 而要先next一下( );
  11. 在没有先调用next 就调用remove方法是会抛出异常的。
  12. 这个和MySQL中的ResultSet很类似
  13. */
  14. default void remove()
  15. {
  16. throw new UnsupportedOperationException("remove");
  17. }
  18. }
  19.  

default修饰符,这也是Java 8后新出现的,我们知道,如果我们给一个接口新添加一个方法,那么所有他的具体子类都必须实现此方法,

为了能给接口拓展新功能,而又不必每个子类都要实现此方法,Java 8新加了default关键字,被其修饰的方法可以不必由子类实现,并且由dafault修饰的方法在接口中有方法体,这打破了Java之前对接口方法的规范.

 
 
 

总结 :

一个集合类要想可以迭代遍历,就必须实现Iterable接口,即必须重写Iterable接口的iterator()方法,而iterator()方法必须返回一个迭代器对象。

迭代器对象就是实现了Iterator接口的迭代器类的实例,而迭代器类必须要重写Iterator接口的hasNext() 和 next() 方法,remove方法虽然default,最好根据需要重写

实现Iterable接口的目的就是为了通过重写iterator()方法得到一个实现了Iterator接口的迭代器类的实例,为什么一定要实现Iterable接口,为什么不直接实现Iterator接口呢?

看一下JDK中的集合类,比如List一族或者Set一族,都是实现了Iterable接口,但并不直接实现Iterator接口。 
仔细想一下这么做是有道理的。

因为Iterator接口的核心方法next()或者hasNext() 是依赖于迭代器的当前迭代位置的。 
      如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。 
      当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。 
      除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。 
      但即时这样,Collection也只能同时存在一个当前迭代位置。 
      而Iterable则不然,每次调用都会返回一个从头开始计数的迭代器。 
      多个迭代器是互不干扰的。

迭代器的使用实例

下面是手动迭代的例子,

foreach内部原理其实就是如下实现的(如果要在迭代中删除元素,只能使用手动迭代,不能使用foreach,因为foreach无法调用迭代器的remove方法)

  1. public static void main(String[] args)
  2. {
  3. List<Integer> li = new ArrayList<>();
  4. li.add();
  5. li.add();
  6. li.add();
  7.  
  8. //不使用foreach 而手动迭代
  9. Iterator<Integer> iter = li.iterator(); //获取ArrayList 的迭代器
  10. while(iter.hasNext()) //①先探测能否继续迭代
  11. {
  12. System.out.println(iter.next()); //②后取出本次迭代出的元素
  13. //invoke iter.remove() //③最后如果需要,调用remove
  14. }
  15. }

  

迭代器类的实现实例

AbstractList中实现的迭代器类,可以借鉴参考。

我们实现自己的迭代器的情况很少,毕竟JDK集合足够强大。

源码中有一些保护机制,为了便于理解我删改了。

  1. private class Itr implements Iterator<E>
  2. {
  3. /*
  4. AbstractList 中实现的迭代器,删除了一些细节。不影响理解
  5. Itr为一个priavate成员内部类
  6.  
  7. */
  8. int cursor = ; //马上等待被迭代元素的index
  9.  
  10. //最近一次,已经被迭代出的元素的index,如果这个元素迭代后,被删除了,则lastRet重置为-1
  11. int lastRet = -;
  12.  
  13. public boolean hasNext() {
  14. return cursor != size(); //当前游标值 等于 集合的size() 说明已经不能再迭代了。
  15. }
  16.  
  17. public E next() {
  18. int i = cursor;
  19. E next = get(i);
  20. lastRet = i; //lastRet 保存的是最近一次已经被迭代出去的元素索引
  21. cursor = i + ; //cursor为马上等待被迭代的元素的索引
  22. return next;
  23. }
  24.  
  25. public void remove()
  26. {
  27. if (lastRet < ) //调用remove之前没有调用next
  28. throw new IllegalStateException(); //则抛异常。这就是为什么在使用remove前,要next的原因
  29.  
  30. OuterList.this.remove(lastRet); //从集合中删除这个元素
  31.  
  32. if (lastRet < cursor) //集合删除元素后,集合后面的元素的索引会都减小1,cursor也要同步后移
  33. cursor--;
  34.  
  35. lastRet = -; //重置
  36. }
  37. }

java学习--Iterable 和 Iterator的更多相关文章

  1. Java学习笔记之Iterator和ListIterator

    原文:https://blog.csdn.net/GongchuangSu/article/details/51514380 Iterator接口是对collection进行迭代的迭代器,ListIt ...

  2. 【转】Java学习之Iterator(迭代器)的一般用法 (转)

    [转]Java学习之Iterator(迭代器)的一般用法 (转) 迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭 ...

  3. Java集合【4】-- iterable和Iterator的异同分析详解

    目录 一.iterator介绍 二.iterable接口 三.为什么有Iterator还需要Iterable 一.iterator介绍 iterator接口,也是集合大家庭中的一员.和其他的Map和C ...

  4. Java学习之Iterator(迭代器)的一般用法 (转)

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为"轻量级"对象,因为创建它的代价 ...

  5. Java学习之Iterator(迭代器)的一般用法

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...

  6. Java中的Iterable与Iterator详解

    在Java中,我们可以对List集合进行如下几种方式的遍历: List<Integer> list = new ArrayList<>(); list.add(5); list ...

  7. java 中的 Comparable 和 Comparator 与 Iterable 和 Iterator

    Comparable 和 Comparator Comparable 和 Comparator 是两个关系不大的类,其分别侧重于不同的方面. 其中,接口 Comparable<T> 强行对 ...

  8. Python学习之路day4-列表生成式、生成器、Iterable和Iterator

    一.列表生成式 顾名思义,列表生成式就是用于生成列表的特殊语法形式的表达式. 1.1 语法格式 [exp for iter_var in iterable] 工作过程: 1.通过iter_var迭代i ...

  9. Java学习之Iterator(迭代器)

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...

随机推荐

  1. eclipse中解决git分支合并冲突

    冲突场景: 在master分支上有文件student.py. 在master上增新一个dev分支 在dev分支上修改文件student.py.增加函数def d():,并commit; 在master ...

  2. ROS tf

    一.节点中使用(cpp,python) 1. ros wiki 提供的tutorials 2. https://blog.csdn.net/start_from_scratch/article/det ...

  3. 工控随笔_02_西门子_WinCC的IO域利用C脚本返回值

    WinCC的输入输出域用来显示信息或者接受操作人员的输入.当作为显示功能时,只有直接的变量连接 才能正常的显示,如果使用动态对话框进行设置且用了表达式则不能正确显示. 但是有时候我们在WinCC变量管 ...

  4. 猜测的rpc负载均衡原理,基于dubbo的架构

    集群层(Cluster):封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster.Directory.Router和LoadBalance.将多个服务提供方组 ...

  5. 和2018年年初做管理系统的不同(vuex)

    从2017年底开始做公司批改后台系统(服务内部人员对熊猫小课用户的作业进行批改.对批改员工资结算等)到教务系统(服务于内部人员对熊猫小课等移动端产品的内容进行配置等).ai-boss系统(服务于内部人 ...

  6. 再见VB6!再见程序生涯!

    今天写一篇博文告别使用了15年的VB6,从此终结程序生涯.记得读大学的时候第一学习编程,用VB6嵌入MediaPlayer控件写了一个简易视频播放器,看着视频的画面激动人心,从此就爱上了编程,从此也和 ...

  7. excle删除重复项的行,自定义删除第几个

    在B1输入 =COUNTIF(A$1:A1,A1) 下拉,会有数字1.2.1.2 第二步,选中B列升序排序,排序后,将B列为1的整行删除即可. 再补充下,这样是以姓名为条件来筛选,不会影响你的数据.你 ...

  8. xamarin android 开发

    开始环境vs2017 直接创建android 项目,左边是android studio 的项目目录  右边是vs创建的android 项目目录 结构基本相同,有res对应的Resources文件 加载 ...

  9. jar包冲突排解方法(sbt)

    jar包依赖冲突,版本不兼容会导致各种各样的问题.这里推荐一款sbt插件用于查找项目中的jar包依赖关系,通过该插件可以轻松的看出某个jar包依赖哪些jar,以及某个jar被哪些jar所依赖.此外该插 ...

  10. python守护进程

    1.守护进程 [1]使用runner这个模块直接创建守护进程,非常方便. [2]运行方法:python xxx.py start|stop|restart [3]调用python xxx.py sto ...