[英]How to implement iterator as an attribute of a class in 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,這就是為什么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
}
但是我想避免擔心這些事情並且只是以一種簡單的方式迭代,我可以用迭代器接口做到這一點,但后來我遇到了兩個問題:我已經解釋過的第一個問題已被許多答案解決了,第二個一個是我的數組由一對int組成,我不能使用原始類型的迭代器。
將迭代器維護為類的實例變量非常不尋常。 您只能遍歷數組一次 - 可能不是您想要的。 更有可能的是,您希望您的類為想要遍歷數組的任何人提供迭代器。 下面是一個更傳統的迭代器。
Java 5+代碼 - 我沒有嘗試編譯或運行,因此它可能包含錯誤(現在不在dev機器附近)。 它還使用autobox'ing將Integer
轉換為int
。
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 ....
}
另請注意:請注意不要在靜態陣列上達到500元素限制。 如果可以,請考慮使用ArrayList類。
在我看來,最好將MyArray實現為常見的Iterable對象,因此可以在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);
}
}
正如我所說,你可以在for語句中使用它:
private static void test(MyArray<String> strArray)
{
for (String str: strArray) {
// do something
}
}
迭代器是一個接口。 Iterator<E>
表示只有Object可以到這里(E)。 Iterator<Integer>
是合法的,但Integer<int>
不是因為int是原始數據類型
您可以將數組更改為ArrayList ,然后遍歷此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());
}
}
}
我的建議是讓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();
}
}
}
}
更新:根據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,因為它還負責維護數組。 簡單的封裝原理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.