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

如何在Java中将迭代器实现为类的属性,java,iterator,Java,Iterator,假设我有一个简单的MyArray类,它有两个简单的方法:add、delete和一个迭代器。在主要方法中,我们可以看到应该如何使用它: 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 v

假设我有一个简单的MyArray类,它有两个简单的方法:add、delete和一个迭代器。在主要方法中,我们可以看到应该如何使用它:

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本身应该实现迭代器接口?这是如何解决的

编辑:

好的,谢谢大家。这是一个简单的示例,说明了我要做什么,所以不必关心固定长度数组。我真正想做的是循环FIFO,这就是为什么
start
end
是游标

此循环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
如果(this.start>=this.end)temp\u end=this.end+this.buff.length;
else temp_end=this.end;
int ii;
int j=0;
int[]值=新的int[2];
for(int i=this.start;i是一个接口。
迭代器
,这意味着只有对象可以进入此处(E)。
Iterator
合法,但
Integer
不合法,因为int是基本数据类型

您可以将数组更改为,然后迭代此arraylist。我添加了
getIterator()
方法,该方法返回
arraylist.iterator()
,并在
main()
方法中对其进行测试

import java.util.ArrayList;
import java.util.Iterator;

public class MyArray {
 int start;
 int end;
 ArrayList<Integer> arr;


 public MyArray() {
  this.start = 0;
  this.end = 0;
  arr = new ArrayList<Integer>(500);
 }

 public void add(int el) {
  arr.add(el);
  this.end++;
 }

 public void delete() {
  arr.remove(arr.size()-1);
  this.start++;
 }

 public Iterator<Integer> 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<Integer> it = m.getIterator();

  while(it.hasNext()){
   System.out.println(it.next());
  }

 }

}
import java.util.ArrayList;
导入java.util.Iterator;
公共类MyArray{
int启动;
内端;
ArrayList-arr;
公共MyArray(){
这个.start=0;
这个0.end=0;
arr=新阵列列表(500);
}
公共空白添加(整数){
协议添加(el);
这个.end++;
}
公共作废删除(){
arr.remove(arr.size()-1);
这个.start++;
}
公共迭代器getIterator(){
返回arr.iterator();
}
公共静态void main(字符串[]args){
MyArray m=新的MyArray();
m、 增加(3);
m、 增加(299);
m、 增加(19);
m、 增加(27);
迭代器it=m.getIterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}

MyArray应实现迭代器,因为迭代器还负责维护数组。简单封装原则。

EDIT:这不适用于基元类型的数组: 您可以为此使用阵列:

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

如果您真的想实现自己的迭代器,我建议在这个场景中使用一个内部类。这样您就可以从myIterator访问MyArray.this

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

在我看来,最好将MyArray实现为公共对象,这样就可以在for语句中使用它

我的建议是:

/**
 * My array
 */
public class MyArray<TItem> implements Iterable<TItem>
{
    /**
     * Internal used iterator.
     */
    private class MyArrayIterator<TItem> implements Iterator<TItem>
    {
        private MyArray<TItem> _array;

        /**
         * @param array The underlying array.
         */
        public MyArrayIterator(MyArray<TItem> array)
        {
            this._array = array;
        }

        /**
         * Gets the underlying array.
         * 
         * @return The underlying array.
         */
        public MyArray<TItem> 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<TItem> iterator() {
        // TODO Auto-generated method stub
        return new MyArrayIterator<TItem>(this);
    }
}
/**
*我的阵列
*/
公共类MyArray实现了Iterable
{
/**
*内部使用的迭代器。
*/
私有类MyArrayIterator实现迭代器
{
私有MyArray\u数组;
/**
*@param array是基础数组。
*/
公共MyArrayIterator(MyArray数组)
{
这个。_数组=数组;
}
/**
*获取基础数组。
* 
*@返回底层数组。
*/
公共MyArray getArray(){
返回此。\u数组;
}
@凌驾
公共布尔hasNext(){
//TODO自动生成的方法存根
返回false;
}
@凌驾
下一个公共时间(){
//TODO自动生成的方法存根
返回null;
}
@凌驾
公共空间删除(){
//TODO自动生成的方法存根
}
}
公共空白添加(整数){
//添加
}
公共作废删除(){
//删除
}
@凌驾
公共迭代器迭代器(){
//TODO自动生成的方法存根
返回新的MyArrayIterator(本);
}
}
正如我所说,您可以在for语句中使用它:

private static void test(MyArray<String> strArray)
{
    for (String str: strArray) {
        // do something
    }
}
专用静态无效测试(MyArray strArray)
{
用于(字符串str:strArray){
//做点什么
}
}

我的建议是让
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<Integer> iterator() {

    return new Iterator<Integer>() {
      // 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();
      }
    }
  }


}
公共类MyArray实现Iterable{
// ...
//现在只需要arr作为实例变量。
//int启动;
//内端;
int[]arr;
//我的迭代器;
/**
*从接口上看是不可编辑的。
*/
公共迭代器迭代器(){
返回新的迭代器(){
//要返回的下一个数组位置
int pos=0;
公共布尔hasNext(){
返回位置

更新:根据BertF的评论,我更新了我的代码,以明确说明类
MyArray
的唯一实例变量现在是
arr
。迭代器的状态现在在匿名
迭代器
实现中。因此,您可以创建多个迭代器实例,它们不会干扰每个ot她。

将迭代器作为类的实例变量进行维护是非常不寻常的。您只能遍历数组一次-可能不是您想要的。更可能的情况是,您希望您的类向任何想要遍历数组的人提供迭代器
public class MyArray implements Iterable<Integer> {

    public static class MyIterator implements Iterator<Integer> {

        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<Integer> iterator() {
        return new MyIterator();
    }

    // The rest of MyArray is the same ....

}