Iterator和Iterable的区别以及使用
Iterator和Iterable的区别以及使用
1、什么是迭代器
迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来
Iterable,该接口包含一个能够产生Iterator接口的iterator()方法,并且Iterable对象被foreach用来在序列中移动,因此创建的任何实现了Iterable接口的类都可以将它用于foreach。

1、 Iterable接口:从继承结构中可以看出,Iterable接口是Collection的顶层接口,所以Iterable是数据结构,用来存放数据的地方。
这个接口只是为了让对象实现for-each loop声明而存在的。
iterable接口最重要的方法是:Iterator<T> iterator()//生成迭代器。否则无法实现for-each
default Spliterator<T> spliterator()//在这 Iterable创建描述元素的 Spliterator//Interface Spliterator<T>用于遍历和划分源的元素的对象。所涵盖的spliterator元素的来源可能是,例如,一个数组,一个 Collection,IO通道,或一个函数发生器。
default void forEach(Consumer<? super T> action)
2、 Iterator接口:是定义了迭代逻辑的接口,即:用于遍历Collection(集合类)中数据的标准访问方法。
Iterator的出现是为了替代Enumeration.
它和Enumeration不同的是,它可以删除迭代的内容。并且被更好的命名
这个接口只有四个方法:
boolean hasNext()
E next()
default void remove()
default void forEachRemaining(Consumer<? super E> action)
Iterator接口是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。
如果没有使用Iterator,遍历一个数组的方法是使用索引:
for(int i=0; i<array.size(); i++) { ... get(i) ... }
而访问一个链表(LinkedList)又必须使用while循环:
while((e=e.next())!=null) { ... e.data() ... }
以上两种方法客户端都必须事先知道集合的内部结构,访问代码和集合本身是紧耦合,无法将访问逻辑从集合类和客户端代码中分离出来,每一种集合对应一种遍历方法,客户端代码无法复用。
更恐怖的是,如果以后需要把ArrayList更换为LinkedList,则原来的客户端代码必须全部重写。
而Iterator模式总是用同一种逻辑来遍历集合
客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合。
Iterator源码:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void
forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
在JDK1.5中,还对上面的代码在语法上作了简化(但是限于只读,如果需要remove,还是直接使用iterator):
每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种Iterator,它只需要获得这个Iterator接口即可,这就是面向对象的威力。
3、
为什么一定要去实现Iterable这个接口呢?为什么不直接实现Iterator接口呢?
看一下JDK中的集合类,比如List一族或者Set一族,
都是实现了Iterable接口,但并不直接实现Iterator接口。
仔细想一下这么做是有道理的。因为Iterator接口的核心方法next()或者hasNext()
是依赖于迭代器的当前迭代位置的。
如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。
当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。
除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。
但即时这样,Collection也只能同时存在一个当前迭代位置。
而Iterable则不然,每次调用都会返回一个从头开始计数的迭代器。
多个迭代器是互不干扰的。
借鉴大佬:
http://www.cnblogs.com/highriver/archive/2011/07/27/2077913.html
Iterator和Iterable的区别以及使用的更多相关文章
- iterator与iterable的区别和联系
iterator与iterable 用Iterator模式实现遍历集合Iterator模式是用于遍历集合类的标准访问方法.它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内 ...
- iterator和iterable的区别
相关博客: http://blog.csdn.net/lipengcn/article/details/51700153 Java中Iterable和Iterator的辨析 http ...
- 【转】Python 中 Iterator和Iterable的区别
Python中 list,truple,str,dict这些都可以被迭代,但他们并不是迭代器.为什么? 因为和迭代器相比有一个很大的不同,list/truple/map/dict这些数据的大小是确定的 ...
- Python 中 Iterator和Iterable的区别
Python中 list,truple,str,dict这些都可以被迭代,但他们并不是迭代器.为什么? 因为和迭代器相比有一个很大的不同,list/truple/map/dict这些数据的大小是确定的 ...
- Iterator 和 Iterable 区别和联系
首先预览下Java源码中的Iterator和Iterable: Iterable接口: public interface Iterable<T> {//这里只摘录接口中的抽象方法 /** ...
- for,foreach,iterator的用法和区别
for,foreach,iterator的用法和区别 相同点: 三个都可以用来遍历数组和集合不同点:1.形式差别 for的形式是for(int i=0;i<arr.size();i++){. ...
- 14、Iterator跟ListIterator的区别
14.Iterator与ListIterator的区别 在使用List,Set的时候,为了实现对其数据的遍历,会经常使用到Iterator(跌代器).使用跌代器,不需要干涉其遍历的过程,只需要每次取出 ...
- 【转】Java迭代:Iterator和Iterable接口
Java迭代 : Iterator和Iterable接口 从英文意思去理解 Iterable :故名思议,实现了这个接口的集合对象支持迭代,是可迭代的.able结尾的表示 能...样,可以做.... ...
- Iterator 与ListIterator的区别
Iterator 与ListIterator的区别: 1.Iterator能够迭代Set和List集合的元素,而ListIterator只能迭代List集合的元素 2.Iterator只能前向迭代,L ...
随机推荐
- 第一章入门篇CSS样式的分类、盒模型
1.CSS样式的分类 CSS样式分为一项4种: 1.内联样式表,直接写在元素style属性里面的样式,如 <p style="color:red;">内联样式</ ...
- (已解决)Eclipsez中打不开c++文件,显示Editor could not be initialized.
新建的游戏导入Eclipse能正常运行,配置什么的都弄好了,游戏运行无任何问题!问题是:关闭Eclipse后,重新打开,就会出现An internal error occurred during: & ...
- LA 3890 Most Distant Point from the Sea(半平面交)
Most Distant Point from the Sea [题目链接]Most Distant Point from the Sea [题目类型]半平面交 &题解: 蓝书279 二分答案 ...
- 解决React Native使用Fetch API请求网络报Network request failed
问题来源: 1 . 在测试fetch数据请求时,Xcode9.0以上的无法请求https, 需要在Xcode中加载项目后修改Info.plist的相关配置,具体如下参考 问题及解决方法一模一样,不再重 ...
- js执行上下文
js在执行是会有一个“准备工作”: 主要内容有 1.变量.函数表达式——>变量声明,默认赋值为undefined: 2.this——>赋值: 3.函数声明——>赋值: 这三种数据的准 ...
- 删掉centos原有的openjdk并安装sun jdk
[环境变量]删掉centos原有的openjdk并安装sun jdk 一.卸载原有openjdk rpm -qa | grep java 之后,将展示出来的全部卸载掉,我这里是5个 rpm -e ...
- IE初始
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 环形数组 最大子段和 dp
题目链接:https://nanti.jisuanke.com/t/36118 环形数组的连续最大子段和,有两种情况. 1.最大和的这个子段没有包含头尾.所以直接dp[i] = max(dp[i-1] ...
- sublime text3 增加代码片段(snipper)
有时候编写代码时有些代码片段经常会用到,如果能将这些代码片段整理,再在需要的时候通过某些条件触发,那无疑是非常方便的! 创建方法:工具->插件开发->新建代码片段 默认产生的内容是: &l ...
- html5-section元素
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...