从英文意思去理解

Iterable :故名思议,实现了这个接口的集合对象支持迭代,是可迭代的。able结尾的表示 能...样,可以做...。
Iterator:   在英语中or 结尾是都是表示 ...样的人 or ... 者。如creator就是创作者的意思。这里也是一样:iterator就是迭代者,我们一般叫迭代器,它就是提供迭代机制的对象,具体如何迭代,都是Iterator接口规范的。
 
 
 

Iterable

一个集合对象要表明自己支持迭代,能有使用foreach语句的特权,就必须实现Iterable接口,表明我是可迭代的!然而实现Iterable接口,就必需为foreach语句提供一个迭代器。
这个迭代器是用接口定义的 iterator方法提供的。也就是iterator方法需要返回一个Iterator对象。

foreach只能用于数组和实现了Iterable接口的类

//Iterable JDK源码
//可以通过成员内部类,方法内部类,甚至匿名内部类去实现Iterator public interface Iterable<T>
{ Iterator<T> iterator();
}

Iterator

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

1、每次在迭代前   ,先调用hasNext()探测是否迭代到终点(本次还能再迭代吗?)。
2、next方法不仅要返回当前元素,还要后移游标cursor
3、remove()方法用来删除最近一次已经迭代出的元素
4、 迭代出的元素是原集合中元素的拷贝(重要)
5、配合foreach使用
//Iterator接口的JDK源码,注释为整理建议使用Iterator的正确姿势

public interface Iterator<E> {

    boolean hasNext();    //每次next之前,先调用此方法探测是否迭代到终点

    E next();            //返回当前迭代元素 ,同时,迭代游标后移

     /*删除最近一次已近迭代出出去的那个元素。
只有当next执行完后,才能调用remove函数。
比如你要删除第一个元素,不能直接调用 remove() 而要先next一下( );
在没有先调用next 就调用remove方法是会抛出异常的。
这个和MySQL中的ResultSet很类似
*/
void remove()
{
throw new UnsupportedOperationException("remove");
}
}

迭代的具体细节

需要理解的地方

1、hasNext , next  , remove 的调用顺序

2、迭代出来的是原集合元素拷贝!

下面是手动迭代的例子,foreach的原理和它一样。

public static void main(String[] args)
{ List<Integer> li = new ArrayList<>(); li.add(1);
li.add(2);
li.add(3);

//不使用foreach 而手动迭代
Iterator<Integer> iter = li.iterator(); //获取ArrayList 的迭代器 while(iter.hasNext()) //①先探测能否继续迭代
{
System.out.println(iter.next()); //②后取出本次迭代出的元素 //invoke remove() //③最后如果需要,调用remove } }

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

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

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

private class Itr implements Iterator<E> 
{
/*
AbstractList 中实现的迭代器,删除了一些细节。不影响理解
Itr为一个priavate成员内部类 */ int cursor = 0; //马上等待被迭代元素的index //最近一次,已经被迭代出的元素的index,如果这个元素迭代后,被删除了,则lastRet重置为-1 int lastRet = -1; public boolean hasNext() {
return cursor != size(); //当前游标值 等于 集合的size() 说明已经不能再迭代了。
} public E next() { int i = cursor;
E next = get(i);
lastRet = i; //lastRet 保存的是最近一次已经被迭代出去的元素索引
cursor = i + 1; //cursor为马上等待被迭代的元素的索引
return next; } public void remove()
{ if (lastRet < 0) //调用remove之前没有调用next
throw new IllegalStateException(); //则抛异常。这就是为什么在使用remove前,要next的原因 OuterList.this.remove(lastRet); //从集合中删除这个元素 if (lastRet < cursor) //集合删除元素后,集合后面的元素的索引会都减小1,cursor也要同步后移
cursor--; lastRet = -1; //重置 } }

迭代出来的元素都是原来集合元素的拷贝

Java集合中保存的元素实质是对象的引用(可以理解为C中的指针),而非对象本身。

迭代出的元素也就都是 引用的拷贝,结果还是引用。那么,如果集合中保存的元素是可变类型的,我们就可以通过迭代出的元素修改原集合中的对象。

而对于不可变类型,如String  基本元素的包装类型Integer 都是则不会反应到原集合中。

为了便于理解,画张图:

验证代码:

public class Main
{ public static void main(String[] args)
{ List<Person> li = new ArrayList<>(); Person p = new Person("Tom"); li.add(p); for(Person ap: li)
{
ap.setName("Jerry");
} System.out.println(li.get(0).getName()); //Jerry not Tom } } class Person
{ public Person(String name)
{
this.name = (name==null?"":name); } private String name; public String getName()
{
return name;
} public void setName(String name)
{
if(name == null)
name = "";
this.name = name;
} }

小试牛刀,让自己的类支持迭代。

public class Main
{ public static void main(String[] args)
{ MyString s = new MyString("1234567"); for(char c:s)
{
System.out.println(c);
} } } class MyString implements Iterable<Character>
{ private int length = 0;
private String ineers = null; public MyString(String s)
{
this.ineers = s;
this.length = s.length(); } @Override
public Iterator<Character> iterator()
{ class iter implements Iterator<Character> //方法内部类
{
private int cur= 0; @Override
public boolean hasNext()
{
return cur != length;
} @Override
public Character next()
{ Character c = ineers.charAt(cur);
cur++;
return c;
} public void remove()
{
// do nothing } }
return new iter(); //安装Iterable接口的约定,返回迭代器 } }

Java迭代 : Iterator和Iterable接口的更多相关文章

  1. 【转】Java迭代:Iterator和Iterable接口

    Java迭代 : Iterator和Iterable接口 从英文意思去理解 Iterable :故名思议,实现了这个接口的集合对象支持迭代,是可迭代的.able结尾的表示 能...样,可以做.... ...

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

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

  3. java 集合框架(二)Iterable接口

    Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素,我们可以看下它的成员方法 修饰符和返回值 方法名 描述 Iterator<T> iter ...

  4. Java 迭代接口:Iterator、ListIterator 和 Spliterator

    1. 简介 当我们使用 for 或 while 循环来遍历一个集合的元素,Iterator 允许我们不用担心索引位置,甚至让我们不仅仅是遍历一个集合,同时还可以改变它.例如,你如果要删除循环中的元素, ...

  5. java集合-Iterator迭代

    我们常常使用 JDK 提供的迭代接口进行 Java 集合的迭代. Iterator iterator = list.iterator(); while(iterator.hasNext()){ Str ...

  6. Java中Iterator类的详细介绍

    迭代器模式:就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节. 概述 Java集合框架的集合类,我们有时候称之为容器.容器的种类有很多种,比如ArrayList.Li ...

  7. iterator和iterable的区别

    相关博客:  http://blog.csdn.net/lipengcn/article/details/51700153         Java中Iterable和Iterator的辨析 http ...

  8. Java之iterator迭代器和iterable接口

    java.lang.Iterable java.util.Iterator Iterator是迭代器类,而Iterable是接口. 好多类都实现了Iterable接口,这样对象就可以调用iterato ...

  9. java中的Iterator和Iterable 区别

    java.lang.Iterable java.util.Iterator 来自百度知道: Iterator是迭代器类,而Iterable是接口. 好多类都实现了Iterable接口,这样对象就可以调 ...

随机推荐

  1. cf 333b

    G - Chips Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit S ...

  2. SU Demos-04Deconvolution-02Wiener_Levinson

    本Demo共有4个脚本,我只看了第一个,后面的3个不熟悉,就不往这里贴图了,望谅解. 不足之处,欢迎批评指正. 先看readme 生成数据所需的c程序 make上述c程序时需要的makefile(本人 ...

  3. 模拟 ZOJ 3878 Convert QWERTY to Dvorak

    题目传送门 /* 模拟:手敲map一一映射,累! 除了忘记读入字符串不能用gets用getline外还是很顺利的AC了:) */ #include <cstdio> #include &l ...

  4. 组合数学(全排列)+DFS CSU 1563 Lexicography

    题目传送门 /* 题意:求第K个全排列 组合数学:首先,使用next_permutation 函数会超时,思路应该转变, 摘抄网上的解法如下: 假设第一位是a,不论a是什么数,axxxxxxxx一共有 ...

  5. CodeForces Round 194 Div2

    A. Candy Bagstime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputs ...

  6. BZOJ1035 : [ZJOI2008]Risk

    首先要将这个图连通,方法是通过扫描线+set求出每个连通块最高的点上方的第一条边,然后向交点连边. 然后把边拆成两条双向边,每次找到一条没走过的边,找到极角排序后它的反向边的后继,直到回到这条边.根据 ...

  7. HDU 1241 (DFS搜索+染色)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=1241 题目大意:求一张地图里的连通块.注意可以斜着连通. 解题思路: 八个方向dfs一遍,一边df ...

  8. COJ986 WZJ的数据结构(负十四)

    WZJ的数据结构(负十四) 难度级别:D: 运行时间限制:6000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小 ...

  9. OpenCV 3.0 VS2010 Configuration

    Add in the system Path: C:\opencv\build\x86\vc10\bin; Project->Project Property->Configuration ...

  10. hdu 4310 Hero

    这道题是道算是一道很简单的贪心题了,但是要注意排序的依据,这道题是按照dps/hp的从大到小排序的,然后计算总的sumhp即可. #include"iostream" #inclu ...