基础大杂烩 -- 目录

用Iterator模式实现遍历集合 

Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。

例如,如果没有使用Iterator,遍历一个数组的方法是使用索引: for(int i=0; i<array.size(); i++) { ... get(i) ... }

而访问一个链表(LinkedList)又必须使用while循环: while((e=e.next())!=null) { ... e.data() ... }

以上两种方法客户端都必须事先知道集合的内部结构,访问代码和集合本身是紧耦合,无法将访问逻辑从集合类和客户端代码中分离出来,每一种集合对应一种遍历方法,客户端代码无法复用。

更恐怖的是,如果以后需要把ArrayList更换为LinkedList,则原来的客户端代码必须全部重写。

解决以上问题,Iterator模式总是用同一种逻辑来遍历集合: for(Iterator it = c.iterater(); it.hasNext(); ) { ... }

        奥秘在于客户端自身不维护遍历集合的"指针",所有的内部状态(如当前元素位置,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂方法生成,因此,它知道如何遍历整个集合。

客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合。

首先看看Java.util.Iterator接口的定义: 
                public interface Iterator { boolean hasNext(); Object next(); void remove(); }

依赖前两个方法就能完成遍历,典型的代码如下: 
                for(Iterator it = c.iterator(); it.hasNext(); ) { Object o = it.next(); // 对o的操作... }

每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回 SetIterator,Tree可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种 Iterator,它只需要获得这个Iterator接口即可,这就是面向对象的威力。

所有集合类都实现了 Collection 接口,而 Collection 继承了 Iterable 接口。

/** * Implementing this interface allows an object to be the target of * the "foreach" statement. * * @param <T> the type of elements returned by the iterator * * @since 1.5 */
public interface Iterable<T> {  /** * Returns an iterator over a set of elements of type T. * * @return an Iterator. */  Iterator<T> iterator();
}  

而在具体的实现类中(比如 ArrayList),则在内部维护了一个 Itr 内部类,该类继承了 Iterator 接口,它的hasNext() 和 next() 方法是和 ArrayList 实现相耦合的。当调用 ArrayList 对象的 iterator() 方法的时候,返回该类 Itr 的一个实例,从而实现遍历 ArrayList 的功能。

    /*** Returns an iterator over the elements in this list in proper sequence.** <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.** @return an iterator over the elements in this list in proper sequence*/public Iterator<E> iterator() {return new Itr();}/*** An optimized version of AbstractList.Itr*/private class Itr implements Iterator<E> {int cursor;       // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;public boolean hasNext() {return cursor != size;}@SuppressWarnings("unchecked")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];}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();}}@Override@SuppressWarnings("unchecked")public void forEachRemaining(Consumer<? super E> consumer) {Objects.requireNonNull(consumer);final int size = ArrayList.this.size;int i = cursor;if (i >= size) {return;}final Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length) {throw new ConcurrentModificationException();}while (i != size && modCount == expectedModCount) {consumer.accept((E) elementData[i++]);}// update once at end of iteration to reduce heap write trafficcursor = i;lastRet = i - 1;checkForComodification();}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}

为什么一定要去实现Iterable这个接口呢?为什么不直接实现Iterator接口呢?

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

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

啦啦啦

转载于:https://www.cnblogs.com/ClassNotFoundException/p/7092041.html

大杂烩 -- Iterator 和 Iterable 区别和联系相关推荐

  1. java中的Iterator和Iterable 区别

    原文:http://perfy315.iteye.com/blog/1459201 ---------------------------------------------------------- ...

  2. 【JDK源码】Iterator与Iterable的实现与区别

    –本文前言–     在介绍Iterator与Iterable接口之前,需要了解Iterator与Iterable接口在Java类库家族谱中的地位.如下图0-1所示.     [版权声明]归CSDN账 ...

  3. java iterable和iterator_在Java中将Iterator转换为Iterable

    假设以下是具有整数值的迭代器-Iterator iterator = Arrays.asList(20, 40, 60, 80, 100, 120, 150, 200).iterator(); 现在, ...

  4. Python 中 Iterator和Iterable的区别

    Python中 list,truple,str,dict这些都可以被迭代,但他们并不是迭代器.为什么? 因为和迭代器相比有一个很大的不同,list/truple/map/dict这些数据的大小是确定的 ...

  5. python iterator iterable_Python中Iterator和Iterable的区别

    python中list, str,truple,  dict都是可以被迭代的,但他们不是迭代器.why? list/truple/map/dict这些数据的大小是确定的,我们可以准确知道他们的size ...

  6. Iterator 和 Iterable的区别

    1.Collection实现了Itarable接口,这是为了给其子类提供规范的遍历方法,比如ArrayList使用数组存储,HashSet使用散列存储,其遍历方法肯定是不一致的,要求所有子类实现统一的 ...

  7. java--迭代(一)Iterator和Iterable接口

    摘自:http://www.cnblogs.com/redcoatjk/articles/4863340.html Iterable:顾名思义,实现了这个接口的对象支持迭代,是可迭代的. Iterat ...

  8. Iterator、Iterable接口的使用及详解

    Java集合类库将集合的接口与实现分离.同样的接口,可以有不同的实现. Java集合类的基本接口是Collection接口.而Collection接口必须实现Iterator接口. 以下图表示集合框架 ...

  9. iterator与iterable

    用Iterator模式实现遍历集合 Iterator模式是用于遍历集合类的标准访问方法.它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构. 例如,如果没有使用Itera ...

  10. java中iterable_java中的Iterator和Iterable

    1.Iterable接口在java.lang包中:Iterator接口在java.util包中 2.Iterable中只有一个方法,那就是返回一个Iterator迭代器:Iterator iterat ...

最新文章

  1. 漫画:HTTP之大明邮差
  2. TensorFlow 官方文档中文版发布啦(持续维护)
  3. 4.10 风格代价函数-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
  4. oracle pl/sql 中目录的创建
  5. 算法练习day1——190318(二分查找)
  6. 单片机方波幅度调节c语言,为什么我用单片机做的频率可调的方波输出会有尖刺,而且会断...
  7. MyBatis基础知识概述
  8. 定义python函数时如果没有return_定义 Python 函数时,如果函数中没有 return 语句,则默认返回空值 None 。_学小易找答案...
  9. eclipse get set 自动添加注释
  10. java作业——Day0014
  11. 解决iPhone、iPad 或 iPod touch 无法连接Wi-Fi网络问题
  12. 如何在 CSS 中将表格居中?
  13. win7 按修改时间范围文件搜索
  14. 银河麒麟Kylin_s10_sp3安装Oracle11g(FS)(官方补丁认证)(亲测有效)
  15. iPhone14pro紫色“掉漆”/ 苹果英伟达拒绝台积电涨价/ DALL·E取消排队...今日更多新鲜事在此...
  16. ARM与DSP的区别
  17. 视频加密选择在线加密还是软件加密好?
  18. 苹果呼叫转移设置不了_苹果手机也可以开启电信VoLTE!
  19. Matlab figure去白边
  20. ImageNet1K的下载与使用

热门文章

  1. Linux编译错误:对‘sem_init/sem_wait/sem_destroy’等未定义的引用
  2. 字符串 -- 3.1 Valid Palindrome -- 图解
  3. 阅读分布式锁文章总结
  4. ajax 保存xmldoc对象,AJAX XML 实例
  5. 数据库与表的操作之创建表(CREATE TABLE)
  6. 【渝粤教育】国家开放大学2018年春季 7392-21FMatlab语言及其应用 参考试题
  7. [渝粤教育] 西南科技大学 管理学原理 在线考试复习资料(4)
  8. 数据预处理第7讲:具有离群点数据的缩放方法比较
  9. C语言获取系统时间的几种方式 !
  10. JavaScript中的数据类型和数据类型转换