java学习--Iterable 和 Iterator
Iterable
Iterable :故名思议,实现了这个接口的集合对象支持迭代,是可迭代的。
- //Iterable JDK源码
- //可以通过成员内部类,方法内部类,甚至匿名内部类去实现Iterator
- public interface Iterable<T>
- {
- Iterator<T> iterator();
- }
Iterator
包含3个方法: hasNext , next , remove。remove按需求实现,一般它很少用到,以至于Eclipse接口方法自动补全时,都忽略了remove放方法。
- //Iterator接口的JDK源码,注释为整理建议使用Iterator的正确姿势
- public interface Iterator<E> {
- boolean hasNext(); //每次next之前,先调用此方法探测是否迭代到终点
- E next(); //返回当前迭代元素 ,同时,迭代游标后移
- /*删除最近一次已近迭代出出去的那个元素。
- 只有当next执行完后,才能调用remove函数。
- 比如你要删除第一个元素,不能直接调用 remove() 而要先next一下( );
- 在没有先调用next 就调用remove方法是会抛出异常的。
- 这个和MySQL中的ResultSet很类似
- */
- default void remove()
- {
- throw new UnsupportedOperationException("remove");
- }
- }
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方法)
- public static void main(String[] args)
- {
- List<Integer> li = new ArrayList<>();
- li.add();
- li.add();
- li.add();
- //不使用foreach 而手动迭代
- Iterator<Integer> iter = li.iterator(); //获取ArrayList 的迭代器
- while(iter.hasNext()) //①先探测能否继续迭代
- {
- System.out.println(iter.next()); //②后取出本次迭代出的元素
- //invoke iter.remove() //③最后如果需要,调用remove
- }
- }
迭代器类的实现实例
AbstractList中实现的迭代器类,可以借鉴参考。
我们实现自己的迭代器的情况很少,毕竟JDK集合足够强大。
源码中有一些保护机制,为了便于理解我删改了。
- private class Itr implements Iterator<E>
- {
- /*
- AbstractList 中实现的迭代器,删除了一些细节。不影响理解
- Itr为一个priavate成员内部类
- */
- int cursor = ; //马上等待被迭代元素的index
- //最近一次,已经被迭代出的元素的index,如果这个元素迭代后,被删除了,则lastRet重置为-1
- int lastRet = -;
- public boolean hasNext() {
- return cursor != size(); //当前游标值 等于 集合的size() 说明已经不能再迭代了。
- }
- public E next() {
- int i = cursor;
- E next = get(i);
- lastRet = i; //lastRet 保存的是最近一次已经被迭代出去的元素索引
- cursor = i + ; //cursor为马上等待被迭代的元素的索引
- return next;
- }
- public void remove()
- {
- if (lastRet < ) //调用remove之前没有调用next
- throw new IllegalStateException(); //则抛异常。这就是为什么在使用remove前,要next的原因
- OuterList.this.remove(lastRet); //从集合中删除这个元素
- if (lastRet < cursor) //集合删除元素后,集合后面的元素的索引会都减小1,cursor也要同步后移
- cursor--;
- lastRet = -; //重置
- }
- }
java学习--Iterable 和 Iterator的更多相关文章
- Java学习笔记之Iterator和ListIterator
原文:https://blog.csdn.net/GongchuangSu/article/details/51514380 Iterator接口是对collection进行迭代的迭代器,ListIt ...
- 【转】Java学习之Iterator(迭代器)的一般用法 (转)
[转]Java学习之Iterator(迭代器)的一般用法 (转) 迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭 ...
- Java集合【4】-- iterable和Iterator的异同分析详解
目录 一.iterator介绍 二.iterable接口 三.为什么有Iterator还需要Iterable 一.iterator介绍 iterator接口,也是集合大家庭中的一员.和其他的Map和C ...
- Java学习之Iterator(迭代器)的一般用法 (转)
迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为"轻量级"对象,因为创建它的代价 ...
- Java学习之Iterator(迭代器)的一般用法
迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...
- Java中的Iterable与Iterator详解
在Java中,我们可以对List集合进行如下几种方式的遍历: List<Integer> list = new ArrayList<>(); list.add(5); list ...
- java 中的 Comparable 和 Comparator 与 Iterable 和 Iterator
Comparable 和 Comparator Comparable 和 Comparator 是两个关系不大的类,其分别侧重于不同的方面. 其中,接口 Comparable<T> 强行对 ...
- Python学习之路day4-列表生成式、生成器、Iterable和Iterator
一.列表生成式 顾名思义,列表生成式就是用于生成列表的特殊语法形式的表达式. 1.1 语法格式 [exp for iter_var in iterable] 工作过程: 1.通过iter_var迭代i ...
- Java学习之Iterator(迭代器)
迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...
随机推荐
- eclipse中解决git分支合并冲突
冲突场景: 在master分支上有文件student.py. 在master上增新一个dev分支 在dev分支上修改文件student.py.增加函数def d():,并commit; 在master ...
- ROS tf
一.节点中使用(cpp,python) 1. ros wiki 提供的tutorials 2. https://blog.csdn.net/start_from_scratch/article/det ...
- 工控随笔_02_西门子_WinCC的IO域利用C脚本返回值
WinCC的输入输出域用来显示信息或者接受操作人员的输入.当作为显示功能时,只有直接的变量连接 才能正常的显示,如果使用动态对话框进行设置且用了表达式则不能正确显示. 但是有时候我们在WinCC变量管 ...
- 猜测的rpc负载均衡原理,基于dubbo的架构
集群层(Cluster):封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster.Directory.Router和LoadBalance.将多个服务提供方组 ...
- 和2018年年初做管理系统的不同(vuex)
从2017年底开始做公司批改后台系统(服务内部人员对熊猫小课用户的作业进行批改.对批改员工资结算等)到教务系统(服务于内部人员对熊猫小课等移动端产品的内容进行配置等).ai-boss系统(服务于内部人 ...
- 再见VB6!再见程序生涯!
今天写一篇博文告别使用了15年的VB6,从此终结程序生涯.记得读大学的时候第一学习编程,用VB6嵌入MediaPlayer控件写了一个简易视频播放器,看着视频的画面激动人心,从此就爱上了编程,从此也和 ...
- excle删除重复项的行,自定义删除第几个
在B1输入 =COUNTIF(A$1:A1,A1) 下拉,会有数字1.2.1.2 第二步,选中B列升序排序,排序后,将B列为1的整行删除即可. 再补充下,这样是以姓名为条件来筛选,不会影响你的数据.你 ...
- xamarin android 开发
开始环境vs2017 直接创建android 项目,左边是android studio 的项目目录 右边是vs创建的android 项目目录 结构基本相同,有res对应的Resources文件 加载 ...
- jar包冲突排解方法(sbt)
jar包依赖冲突,版本不兼容会导致各种各样的问题.这里推荐一款sbt插件用于查找项目中的jar包依赖关系,通过该插件可以轻松的看出某个jar包依赖哪些jar,以及某个jar被哪些jar所依赖.此外该插 ...
- python守护进程
1.守护进程 [1]使用runner这个模块直接创建守护进程,非常方便. [2]运行方法:python xxx.py start|stop|restart [3]调用python xxx.py sto ...