Java Iterator
およびIterable
インターフェースを理解しようとしています
私はこのクラスを書いています
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
の両方を同じクラスに実装する必要があります。彼らは異なることをします。イテレータは当然ステートフル-使用を繰り返すと、世界観を更新する必要があります。ただし、イテレータは、新しいイテレータを作成できる必要があるだけです。特に、複数のイテレータを同じ元のイテレータで同時に動作させることができます。
あなたの現在のアプローチはほとんど問題ありません-私が変更したい実装の側面がありますが、責任の分離という点では問題ありません。
あなたは最初の試みで順調に進んでいました。 MyClass
は_Iterable<String>
_を実装するだけでよく、Iterable<String>.iterator()
から戻るには_Iterator<String>
_実装を提供する必要があります。
MyClassIterator
をMyClass
の外に置く必要はありません。ほとんどの場合、_Iterator<String>
_を直接使用する必要はないからです(_for .. in ..
_構文によって暗黙的に使用されます)。 _Iterable<String>
_ s)で、他のすべての場合、実装に実際に追加の動作を追加しない限り、インターフェイスで十分です(これはおそらく行う必要はありません)。
これが私がそれをする方法です、インライン化されたコメントを見てください:
_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();
}
};
}
}
_
イテレータはシングルユースであるため、Myclass implements Iterable<String>,Iterator<String>{
を実行しないでください。リストイテレータを除いて、それらを最初に戻す方法はありません。
ちなみに、スキップすることができます
MyClass myClass;
public MyClassInterator(MyClass m){
myclass=m;
}
参照する代わりに
myClass
参照
MyClass.this
内部クラスは静的ではないため、MyClass.this
はそれを作成した囲んでいるクラスのインスタンスを参照します。
これは、IterableとIteratorを同時に実装するための標準的な方法だと思います。
// return list of neighbors of v
public Iterable<Integer> adj(int v) {
return new AdjIterator(v);
}
// support iteration over graph vertices
private class AdjIterator implements Iterator<Integer>, Iterable<Integer> {
private int v;
private int w = 0;
AdjIterator(int v) {
this.v = v;
}
public Iterator<Integer> iterator() {
return this;
}
public boolean hasNext() {
while (w < V) {
if (adj[v][w]) return true;
w++;
}
return false;
}
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return w++;
}
参照 https://algs4.cs.princeton.edu/41graph/AdjMatrixGraph.Java.html 。