如何在Java中将迭代器实现为类的属性

假设我有这个简单的MyArray类,有两个简单的方法:add,delete和iterator。 在main方法中,我们可以看到它应该如何使用:

public class MyArray { int start; int end; int[] arr; myIterator it; public MyArray(){ this.start=0; this.end=0; this.arr=new int[500]; it=new myIterator(); } public void add(int el){ this.arr[this.end]=el; this.end++; } public void delete(){ this.arr[this.start]=0; this.start++; } public static void main(String[] args){ MyArray m=new MyArray(); m.add(3); m.add(299); m.add(19); m.add(27); while(m.it.hasNext()){ System.out.println(m.it.next()); } } 

然后MyIterator应该以某种方式实现:

 import java.util.Iterator; public class myIterator implements Iterator{ @Override public boolean hasNext() { // TODO Auto-generated method stub return false; } @Override public Object next() { // TODO Auto-generated method stub return null; } @Override public void remove() { // TODO Auto-generated method stub } 

}

MyIterator应该从MyArray类迭代arr ,从开始结束值; 两者都是MyArray的属性。 因此,由于MyIterator应该使用MyArray属性, MyIterator应该如何实现? 也许我可以在初始化中发送当前对象:

 it=new myIterator(this); 

但我想这不是最好的灵魂。 或者也许MyArray本身应该实现Iterator接口? 这是怎么解决的?

编辑:

好的,谢谢大家。 这是我想要做的一个简单的例子,所以不关心固定长度数组。 我真的想做的是循环FIFO,这就是为什么startend都是游标。

该循环FIFO将是一对整数对的数组,例如,大小为300: int[][] arr=new int[300][2]

当迭代一个循环数组时,我必须小心,如果计数器到达终点并从头开始,所以这就是我解决它的方法:

 if (this.start >= this.end ) temp_end=this.end+this.buff.length; else temp_end=this.end; int ii; int j=0; int[] value=new int[2]; for(int i=this.start; i<temp_end; i++){ ii=i% this.arr.length; value=this.buff[ii]; //do anything with value 

}

但是我想避免担心这些事情并且只是以一种简单的方式迭代,我可以用迭代器接口来做这个,但后来我遇到了两个问题:第一个我已经解释过并且已经被很多答案解决了,第二个一个是我的数组由一对int组成,我不能使用原始类型的迭代器。

将迭代器维护为类的实例变量非常不寻常。 你只能遍历一次数组 – 可能不是你想要的。 更有可能的是,您希望您的类为想要遍历数组的任何人提供迭代器。 下面是一个更传统的迭代器。

Java 5+代码 – 我没有尝试编译或运行,因此它可能包含错误(现在不在dev机器附近)。 它还使用autobox’ing将Integer转换为int

 public class MyArray implements Iterable { public static class MyIterator implements Iterator { private final MyArray myArray; private int current; MyIterator(MyArray myArray) { this.myArray = myArray; this.current = myArray.start; } @Override public boolean hasNext() { return current < myArray.end; } @Override public Integer next() { if (! hasNext()) throw new NoSuchElementException(); return myArray.arr[current++]; } @Override public void remove() { // Choose exception or implementation: throw new OperationNotSupportedException(); // or //// if (! hasNext()) throw new NoSuchElementException(); //// if (currrent + 1 < myArray.end) { //// System.arraycopy(myArray.arr, current+1, myArray.arr, current, myArray.end - current-1); //// } //// myArray.end--; } } .... // Most of the rest of MyArray is the same except adding a new iterator method .... public Iterator iterator() { return new MyIterator(); } // The rest of MyArray is the same .... } 

另请注意:请注意不要在静态数组上达到500元素限制。 如果可以,请考虑使用ArrayList类。

在我看来,最好将MyArray实现为常见的Iterable对象,因此可以在for语句中使用它。

我的建议:

 /** * My array */ public class MyArray implements Iterable { /** * Internal used iterator. */ private class MyArrayIterator implements Iterator { private MyArray _array; /** * @param array The underlying array. */ public MyArrayIterator(MyArray array) { this._array = array; } /** * Gets the underlying array. * * @return The underlying array. */ public MyArray getArray() { return this._array; } @Override public boolean hasNext() { // TODO Auto-generated method stub return false; } @Override public TItem next() { // TODO Auto-generated method stub return null; } @Override public void remove() { // TODO Auto-generated method stub } } public void add(int el){ // do add } public void delete(){ // do delete } @Override public Iterator iterator() { // TODO Auto-generated method stub return new MyArrayIterator(this); } } 

正如我所说,你可以在for语句中使用它:

 private static void test(MyArray strArray) { for (String str: strArray) { // do something } } 

迭代器是一个接口。 Iterator表示只有Object可以到这里(E)。 Iterator是合法的,但Integer不是因为int是原始数据类型

您可以将数组更改为ArrayList ,然后遍历此arraylist。 我添加了getIterator()方法,它返回arraylist.iterator()并在main()方法中测试它

 import java.util.ArrayList; import java.util.Iterator; public class MyArray { int start; int end; ArrayList arr; public MyArray() { this.start = 0; this.end = 0; arr = new ArrayList(500); } public void add(int el) { arr.add(el); this.end++; } public void delete() { arr.remove(arr.size()-1); this.start++; } public Iterator getIterator(){ return arr.iterator(); } public static void main(String[] args) { MyArray m = new MyArray(); m.add(3); m.add(299); m.add(19); m.add(27); Iterator it = m.getIterator(); while(it.hasNext()){ System.out.println(it.next()); } } } 

我的建议是让MyArray实现接口java.lang.Iterable并根据iterator()调用创建迭代器的实例(作为匿名类)。 然后,您可以在foreach构造中直接使用MyArray的实例:

 public class MyArray implements Iterable { // ... // Only arr is needed now as an instance variable. // int start; // int end; int[] arr; // myIterator it; /** * From interface Iterable. */ public Iterator iterator() { return new Iterator() { // The next array position to return int pos = 0; public boolean hasNext() { return pos < arr.length; } public Integer next() { if(hasNext()) return arr[pos++]; else throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } } } } 

更新:根据BertF的评论,我更新了我的代码以表明, MyArray类的唯一实例变量现在是arr 。 迭代器的状态现在位于匿名Iterator实现中。 因此,您可以创建多个不会相互干扰的迭代器实例。

编辑:这不适用于基本类型的数组:您可以使用数组:

it = new Arrays.asList(arr).subList(start, end).iterator(); 编辑结束

如果你真的想要实现自己的迭代器,我建议在这种情况下使用内部类。 这样您就可以从myIterator访问MyArray.this。

 public class MyArray { .... private class myIterator implements Iterator{ .... } } 

MyArray应该实现Iterator,因为它还负责维护数组。 简单的封装原理。