我正在尝试理解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();
}
}
哪一个更好?
答案 0 :(得分:33)
您几乎永远不会在同一个班级同时实施Iterable
和Iterator
。他们做不同的事情。迭代器自然是有状态的 - 当你使用它迭代时,它必须更新它的世界观。但是,迭代只需要能够创建新的迭代器。特别是,你可以让几个迭代器同时在同一个原始迭代上工作。
你目前的做法非常好 - 我会改变实施的各个方面,但在责任分离方面却很好。
答案 1 :(得分:7)
你第一次尝试就走上了正轨。 MyClass
只需要实施Iterable<String>
,这反过来要求您提供从Iterator<String>
返回的Iterable<String>.iterator()
实施。
没有必要将MyClassIterator
放在MyClass
之外,因为在大多数情况下,您甚至不需要直接使用Iterator<String>
(for .. in ..
隐式使用Iterable<String>
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();
}
};
}
}
s)上的语法,在所有其他情况下,除非您实际向实现添加其他行为(您可能不需要这样做),否则接口就足够了。
以下是我的方法,请参阅内联评论:
{{1}}
答案 2 :(得分:2)
您不应该Myclass implements Iterable<String>,Iterator<String>{
,因为迭代器是一次性使用的。除了列表迭代器之外,没有办法将它们返回到开头。
顺便提一下,您可以跳过
MyClass myClass;
public MyClassInterator(MyClass m){
myclass=m;
}
而不是引用
myClass
参考
MyClass.this
您的内部类不是静态的,因此MyClass.this
将引用创建它的封闭类的实例。
答案 3 :(得分:0)
我认为这是同时实现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。