在同一个类中实现 Java Iterator 和 Iterable?

Posted

技术标签:

【中文标题】在同一个类中实现 Java Iterator 和 Iterable?【英文标题】:Implement Java Iterator and Iterable in same class? 【发布时间】:2011-08-15 17:21:35 【问题描述】:

我正在尝试理解 Java IteratorIterable 接口

我正在写这门课

class MyClass implements Iterable<String> 
    public String[] a = null;
    public MyClass(String[] arr) 
        a = arr;    
    

    public MyClassIterator iterator() 
        return new MyClassIterator(this);
    

    public class MyClassIterator implements Iterator<String> 
        private MyClass myclass = null;
        private int count = 0;
        public MyClassIterator(MyClass m) 
            myclass = m;    
        

        public boolean hasNext() 
            return count < myclass.a.length;
        
        public String next() 
            int t = count;
            count++;
            return myclass.a[t];
        

        public void remove() 
            throw new UnsupportedOperationException();
        
       

它似乎正在工作。

我应该有:

Myclass implements Iterable<Stirng>, Iterator<String> 


或者我应该把MyClassIterator放在MyClass之外

class MyClass implements Iterable<String> 
    public String[] a = null;
    public MyClass(String[] arr) 
        a = arr;    
    
    public MyClassIterator iterator() 
        return new MyClassIterator(this);
    



    public class MyClassIterator implements Iterator<String> 
        private MyClass myclass = null;
        private int count = 0;
        public MyClassIterator(MyClass m) 
            myclass = m;    
        

        public boolean hasNext() 
            return count < myclass.a.length;
        
        public String next() 
            int t = count;
            count++;
            return myclass.a[t];
        

        public void remove() 
            throw new UnsupportedOperationException();
        
       

哪个更好?

【问题讨论】:

为什么你的班级需要两者都做?一般来说,您会实现 Iterable,以便有人可以从您的类中获取 Iterator。 【参考方案1】:

您几乎应该从不在同一个类中同时实现IterableIterator。他们做不同的事情。迭代器自然是有状态的 - 当您使用它进行迭代时,它必须更新其对世界的看法。然而,一个可迭代对象只需要能够创建新的迭代器。特别是,您可以让多个迭代器同时处理同一个原始可迭代对象。

您当前的方法非常好 - 我会更改实施的某些方面,但在职责分离方面很好。

【讨论】:

谢谢,我更新了一点我的问题,哪个更好,将 MyClassInterator 放在 MyClass 之外怎么样? @icn:将 MyClassIterator 保留为嵌套类很好。 (尽管是迭代器,而不是交互器。)我建议您将其设为私有静态最终类。毕竟,您不需要能够直接从其他任何地方引用它。 @icn:您应该将MyClassIterator 保留在MyClass 中。您还应该将其设为private 并使该方法返回Iterator&lt;String&gt;。您也不应该将MyClass 传递给构造函数,因为MyClassIterator 是一个内部类,并且隐式引用了MyClass 的周围实例,因此您可以直接在其中访问数组a。跨度> @Jon - 为什么要将内部类设为静态? @Jon: Iterators 通常(包括在这种情况下)非常适合非静态内部类。他没有使用对外部类的隐式引用,但是……他应该使用! =)【参考方案2】:

您的第一次尝试已步入正轨。 MyClass 只需要实现Iterable&lt;String&gt;,这反过来需要你提供一个Iterator&lt;String&gt; 实现来从Iterable&lt;String&gt;.iterator() 返回。

没有必要将MyClassIterator 放在MyClass 之外,因为在大多数情况下,您甚至不需要直接使用Iterator&lt;String&gt;for .. in .. 上的for .. in .. 语法隐式使用它),在所有其他情况下,接口就足够了,除非您实际上向实现添加了其他行为(您可能永远不需要这样做)。

这是我的做法,请参阅内联的 cmets:

import java.util.Iterator;

class MyClass implements Iterable<String>
    public String[] a=null; //make this final if you can
    public MyClass(String[] arr)
        a=arr; //maybe you should copy this array, for fear of external modification
    

    //the interface is sufficient here, the outside world doesn't need to know
    //about your concrete implementation.
    public Iterator<String> iterator()
        //no point implementing a whole class for something only used once
        return new Iterator<String>() 
            private int count=0;
            //no need to have constructor which takes MyClass, (non-static) inner class has access to instance members
            public boolean hasNext()
                //simplify
                return count < a.length;
            
            public String next()
                return a[count++]; //getting clever
            

            public void remove()
                throw new UnsupportedOperationException();
            
        ;
    

【讨论】:

谢谢,因为我们有一个异常“throw new UnsupportedOperationException();”,所以我们应该在程序的某个地方指定要抛出的异常,比如 throw UnsupportedOperationException()? 欢迎您,@icn。是的,在 iterator() 的 cmets 中提及它可能就足够了。实际上,这并不重要,for .. in .. 几乎是唯一在(现代)Java 中直接使用Iterators 的构造,它不会尝试使用remove。事实上,像remove 这样的“可选”接口成员充其量是没有用的,因为消费者几乎不得不假设他们会扔掉。【参考方案3】:

您不应该使用Myclass implements Iterable&lt;String&gt;,Iterator&lt;String&gt;,因为迭代器是一次性使用的。除了列表迭代器之外,没有办法将它们返回到开头。

顺便说一句,你可以跳过

MyClass myClass;
public MyClassInterator(MyClass m)
  myclass=m;  

而不是引用

myClass

参考

MyClass.this

您的内部类不是静态的,因此MyClass.this 将引用创建它的封闭类的实例。

【讨论】:

以上是关于在同一个类中实现 Java Iterator 和 Iterable?的主要内容,如果未能解决你的问题,请参考以下文章

如何在java中实现List集合的遍历

在 Object[] 数组上实现 Java Iterator 和 Iterable 接口

扩展三个在Java中实现接口的类

如何在 Java 类中实现运算符

如何在java中实现接口类

Java中实现多态的机制