A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始


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

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

7 个回复

倒序浏览
看一下JDK中的集合类,比如List一族或者Set一族,
都是实现了Iterable接口,但并不直接实现Iterator接口。

仔细想一下这么做是有道理的。因为Iterator接口的核心方法next()或者hasNext()
是依赖于迭代器的当前迭代位置的。

如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。
当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。
除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。

但即时这样,Collection也只能同时存在一个当前迭代位置。
而Iterable则不然,每次调用都会返回一个从头开始计数的迭代器。
多个迭代器是互不干扰的。

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
Iterable接口实现后的功能是“返回”一个迭代器
而Iterator接口实现后的功能是“使用”一个迭代器
如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。
当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。
也就是说如果直接实现Iterator可能导致指针错误,而实现Iterable的话,每次都是使用新的迭代器,这样就不会出错

点评

嗯,说的不错,赞一个。。。  发表于 2012-4-25 23:51
回复 使用道具 举报
我来补充一些,
Iterator接口是用于遍历Collection的实现类的标准访问方法。其中定义了三个方法:
-----boolean hasNext():如果别迭代的集合元素还没有被遍历,那么返回true。
-----Object next():返回集合里下一个元素。
-----void  remove():删除集合里上一次next方法返回的元素。
注:Iterator本身不提供盛装对象的能力。如果需要创建Interator对象,则必须要有一个被迭代的集合。可以说他没集合引用,就无从谈起迭代集合元素,正是这一点限制了他。
    访问代码和集合本身是紧耦合,无法将访问逻辑从集合类和客户端代码中分离出来,每一种集合对应一种遍历方法,客户端代码无法复用。更恐怖的是,如果以后需要把ArrayList更换为LinkedList,
    则原来的客户端代码必须全部重写。也就是说从软件耦合度上分析,他对集合产生了严重依赖,这种设计模式很不ok,你知道为什么大家都喜欢用Spring3.0框架来做javaEE的中间层吗?
   是的,就是Spring3.0的设计很好,对表现层和持久层的解耦工作做的十分到家。
那么现在Iterable接口就是他的改良。。降低的代码耦合度,是编程效率大大提高。。
回复 使用道具 举报
做了个例子看下吧。
  1. package com.heima;

  2. import java.lang.reflect.Field;
  3. import java.util.Iterator;

  4. public class Teacher implements Iterable{
  5.    
  6.     private String name;
  7.     private int age;
  8.      
  9.      
  10.     public String getName() {
  11.         return name;
  12.     }
  13.     public void setName(String name) {
  14.         this.name = name;
  15.     }
  16.     public int getAge() {
  17.         return age;
  18.     }
  19.     public void setAge(int age) {
  20.         this.age = age;
  21.     }
  22.     public Iterator iterator() {
  23.         return new MyInterator();
  24.     }

  25.      
  26.     public static void main(String[] args) {
  27.         Teacher t = new Teacher();
  28.         t.setName("hello heima!");
  29.         t.setAge(23);
  30.         for (Object o : t) {
  31.             System.out.println(o.toString());
  32.         }
  33.     }
  34.      
  35.      
  36.     private class MyInterator implements Iterator{
  37.             // 属性的索引
  38.         private int cursor=0;
  39.         // 属性的数组
  40.         private Field[] fields = Teacher.class.getDeclaredFields();
  41.          
  42.         public boolean hasNext() {

  43.             return cursor!=(Teacher.class.getDeclaredFields().length);
  44.         }

  45.         public Object next() {
  46.             Object o=null;
  47.             try{
  48.                     // 让内部类可以访问外部类的私有属性的值
  49.                 fields[cursor].setAccessible(true);   
  50.                 o = fields[cursor].getName()+" "+fields[cursor].get(Teacher.this);
  51.                 cursor++;
  52.             }catch(Exception e){
  53.                 System.out.println(e);
  54.             }
  55.             
  56.             return o;
  57.         }

  58.         public void remove() {
  59.             
  60.         }
  61.          
  62.     }
  63. }
复制代码
回复 使用道具 举报
本帖最后由 王明(1988) 于 2012-4-26 00:43 编辑

JAVA中得各种集合实际上都对Iterator接口的3个方法重新覆盖了,而如果要使用foreach方法(增强的for循环)来遍历,那么就必须实现Iterable接口,一般实现方式就如上。
这一点很重要,如果你用实现Iterator接口的话,你的代码会和for循环(或者增强for,while循环)严重的耦合,直接造成,将来你的代码复用性特别差劲。
而我只需要自定义一个自己的迭代器类,在这个类采取继承Iterable接口,仔细看一下我的MyIterator类,是不是解耦工作做的不错!就非常的低耦合。是吧,以后修改,就爽多了。
其实在使用上,我觉得既然java集合大部分都实现了Iterable接口,那么必定是因为他的这个解耦优点,因为这种低耦合度的设计模式,写代码非常爽,
等你用过Spring3.0动态注入bean对象,配置xml文件时,你就明白为什么,要这么用他了。。。。
回复 使用道具 举报
王勃 中级黑马 2012-4-26 00:49:10
7#
本帖最后由 王明(1988) 于 2012-4-26 01:11 编辑

楼上2位说的,当使用Iterator时 ,当集合引用发生传递时,容易丢失迭代集合元素的指针,我想空指针异常不是java的风格吧(那是C++程序员的错误专利),所以java避免出现空指针,
那我们就果断实现Iterable接口吧。
再啰嗦一句:如果想用foreach(增强for)遍历自定义的集合,自定义类通常需要实现Iterable接口。(此句话,是我在java一本参考书上看到的,搬给你)
回复 使用道具 举报
王勃 中级黑马 2012-4-26 01:13:25
8#
刚看了一个贴子,说foreach的。。
ArrayList al=new ArrayList();
                al.add("测试用1");
                al.add("测试用2");
                for (Object object : al) {
                        System.out.println(object);
                }
那么到底为什么可以这样操作呢?
是因为JDK1.5 引入了新的呗称为Iterable的接口, 这个接口能产生一个Iteraror和Iterator()的方法 并且Iterable接口被foreach用来在序列中移动 因此如果你创建任何实现iterable的类都可以将它用于foreach语句中。
因为java集合们大都实现了Iterable接口的缘故。{:soso_e128:}这里表现的就非常解耦啊。。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马