I am trying to understand Java Iterator
and Iterable
interfaces
I am writing this class
class MyClass implements Iterable&
You should not do Myclass implements Iterable<String>,Iterator<String>{
since iterators are single-use. With the exception of list iterators, there's no way to return them to the start.
Incidentally, you can skip the
MyClass myClass;
public MyClassInterator(MyClass m){
myclass=m;
}
and instead of referencing
myClass
reference
MyClass.this
Your inner class is not static, so MyClass.this
will reference the instance of the enclosing class that created it.
You should almost never implement both Iterable
and Iterator
in the same class. They do different things. An iterator is naturally stateful - as you iterate using it, it has to update its view of the world. An iterable, however, only needs to be able to create new iterators. In particular, you could have several iterators working over the same original iterable at the same time.
Your current approach is pretty much okay - there are aspects of the implementation I'd change, but it's fine in terms of the separation of responsibilities.
You were on track with your first try. MyClass
only needs to implement Iterable<String>
, which in turn requires you to provide an Iterator<String>
implementation to return from Iterable<String>.iterator()
.
There's no need to put the MyClassIterator
outside of MyClass
because in most cases you will never even need to directly use the Iterator<String>
(it's used implicitly by the for .. in ..
syntax on Iterable<String>
s), and in all other cases the interface is sufficient unless you actually add additional behavior to the implementation (which you likely won't ever need to do).
Here's how I'd do it, see comments inlined:
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();
}
};
}
}
I suppose this is a standard way to implement the Iterable and Iterator at the same time.
// 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++;
}
Reference https://algs4.cs.princeton.edu/41graph/AdjMatrixGraph.java.html.