Zaimplementować Java Iterator i Iterable w tej samej klasie?
Próbuję zrozumieć Interfejsy Javy Iterator
iIterable
Piszę tę klasę
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();
}
}
}
Wygląda na to, że działa.
Powinienem:
Myclass implements Iterable<Stirng>, Iterator<String> {
}
Lub powinienem umieścić MyClassIterator
na zewnątrz MyClass
jako
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();
}
}
Która jest lepsza? 4 answers
Powinieneś prawie nigdy implementować zarówno Iterable
jak i Iterator
w tej samej klasie. Robią różne rzeczy. Iterator jest naturalnie stateful - gdy iterator używa go, musi zaktualizować swój pogląd na świat. Iterable, jednak tylko musi być w stanie tworzyć nowe Iteratory. W szczególności, możesz mieć kilka iteratorów pracujących nad tą samą oryginalną iteracją w tym samym czasie.
Twoje obecne podejście jest prawie w porządku - istnieją aspekty wdrożenia Zmieniłbym się, ale jest w porządku, jeśli chodzi o podział obowiązków.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 19:00:10
Byłeś na dobrej drodze przy pierwszej próbie. MyClass
musi jedynie zaimplementować Iterable<String>
, co z kolei wymaga dostarczenia Iterator<String>
implementacji do powrotu z Iterable<String>.iterator()
.
Nie ma potrzeby umieszczania MyClassIterator
poza MyClass
, ponieważ w większości przypadków nigdy nie będziesz musiał bezpośrednio używać Iterator<String>
(jest ona używana domyślnie przez składnię for .. in ..
na Iterable<String>
s), a we wszystkich innych przypadkach interfejs jest wystarczający, chyba że faktycznie dodasz dodatkowe zachowanie do implementacji (co prawdopodobnie nie będzie nigdy nie trzeba).
Oto jak bym to zrobił, Zobacz komentarze:
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();
}
};
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 20:00:50
Nie powinieneś robić Myclass implements Iterable<String>,Iterator<String>{
, ponieważ Iteratory są jednorazowego użytku. Z wyjątkiem iteratorów list, nie ma możliwości powrotu ich do początku.
Nawiasem mówiąc, możesz pominąć
MyClass myClass;
public MyClassInterator(MyClass m){
myclass=m;
}
I zamiast odwoływać się
myClass
Odniesienie
MyClass.this
Twoja wewnętrzna klasa nie jest statyczna, więc MyClass.this
będzie odwoływać się do instancji klasy, która ją utworzyła.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 19:01:30
Przypuszczam, że jest to standardowy sposób implementacji Iterable i Iterator w tym samym czasie.
// 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++;
}
Odniesienie https://algs4.cs.princeton.edu/41graph/AdjMatrixGraph.java.html .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-19 04:41:13