Iterator und Collection

Beginner12

Mitglied
Hi, ich hab meine eigen Collection erzeugt und auch ein Iterator. Jedoch mein Programm funtzt nicht so ganz. Es wird nicht das letzte Element zurückgegeben. Ich hab schon ne Idee, woran das liegt jedoch hab noch keine Lösung des Problems gefunden.

Java:
import java.util.*;

public class Apply {

	Apply(){
		
		MyList<String> liste = new MyList<String>("S");
		liste.add("B");
		liste.add("C");          //add all elements
		liste.add("D");
		
		Iterator<String> iter = liste.iterator(); 
		
		;
		
		
		while(iter.hasNext()){
			
			System.out.println(iter.next());    //show all elements 
		}                                                       //das letzte Element wird nicht angezeigt
		
		
		
	}
	
	public static  void main(String[] args){
	
	new Apply();
	
}
}

Java:
import java.util.Iterator;


public class MyList<E> {

           private E elem;

	private MyList<E> next;
	
	MyList(E e){
		elem = e;
	}
	
	MyList(){}
	
	public void add(E e){                // Elemente werde hinzugefügt
		if(next == null)
		 	 next = new MyList<E>(e); 
		else next.add(e);
		
	}

	Iterator<E> iterator() {                     
		return new MyIterator<E>(this);       
	}

	E getElem() {
	
		return elem;
	}

	MyList<E> getNext() {            //Methode, die man später in der Klasse MyIterator braucht
		
		return next;
	}

	MyList<E> getNext2(){
		return this;
	}

	}

Java:
import java.util.Iterator;

public class MyIterator<E> implements Iterator<E> {

          MyList<E> list;
	
	MyIterator(MyList<E> evList) {
		list = evList;
	}


public boolean  hasNext(){
		   
		    return list.getNext() !=null;          //Das Problem ist warscheinlich hier
	}

	
	
	@Override
	public E next() {
		E element = list.getElem();
		list = list.getNext();
		return element;
	}

	@Override
	public void remove() {
		
		}
}

Ich komme einfach nicht weiter, demzufolge bitte ich euch um ne kleine Hilfe;
 
Mhm, ja evtl. etwas komisch implementiert 🙂
Aber die Fehlerstelle hast du ja schon gefunden, könntest dort mal
Java:
	public boolean hasNext() {
		return list != null && list.getElem() != null; //list != null !!!!! (je nachdem ob null erlaubt ist oder nicht als Element :)
	}
ausprobieren.
 
Danke schön für ne schnelle Anwort. Ich hab schon ein bißchen probiert, den Fehler selbst zu
beseitigen und hab so was ausgedacht:

Java:
public boolean hasNext(){
		  
		    if(list.getNext()!=null){
                           return true;   
		
	    }else	if(list.getNext()==null && list.getElem()!=null){
			   return true;
	
		    
	}else return false;
	
}
Da hab ich so gedacht :
1. Wenn das nächste Element ungleich null ist, dann wird true zurückgegeben.
2. Wenn das nächste Element null ist , aber list.getElem()!=null ist dann wird auch true zurückgeliefert.(Also wenn es sich um das letzte Element handelt da ist das nächste null, aber das letzte Element ist noch da)
3. Wenn keine der oben genannten Bedingungen gefüllt wurde, dann wird false zurückgeliefert.

Alle Elemente werden so zurückgegeben, aber auch so ein Exception
Java:
Exception in thread "main" java.lang.NullPointerException
	at MyIterator.hasNext(MyIterator.java:59)
	at Apply.<init>(Apply.java:18)
	at Apply.main(Apply.java:36)
S
B
C
D

Wo ist eigentlich hier der Fehler? Wo ist eigentlich der Unterschied zwischen meiner Halblösung und
deiner?(Deine Lösung funktioniert super).Ich würde auch gern verstehen, um später alles richtig zu machen.

Ich hab so gadacht, oder sind meine Gedanke falsch?
Meine Elemente S -> B - >C -> D -> null

iter.hasNext(); greift auf B und ist ungleich null wird true zurückgeliefert.
iter.next(); wird das erste Element S zurückgegeben .

iter.hasNext(); C ungleich null -> true
iter.next(); B wird zurückgeliefert.

iter.hasNext(); D ungleich null -> true
iter.next(); C wird zurückgegeben.

iter.hasNext(); null
iter.next(); sollte D ausgeben. und das hab ich oben in der Methode implementiert,
wenn list.getNext() null, aber list.getElem!= null dann true .
Aber funktioniert nicht.

Vielen Dank im Voraus!!!
 
Ich hab so gadacht, oder sind meine Gedanke falsch?
Meine Elemente S -> B - >C -> D -> null
Nein, das ist eig. richtig.

Dein Problem ist halt das Iterieren.
Was passiert?
in einer Schleife rufst du jedes mal
Code:
hasNext()
auf, beim ersten Mal schaust du quasi ob S ein Nachfolger hat(das ist ja eig. schon nicht ganz korrekt, du müsstest ja eig. erstmal gucken ob`s S überhaupt gibt). S hat einen Nachfolger also gibst du true zurück -->
Code:
next()
wird aufgerufen usw.
Jetzt bist du dann irgendwann bei D angekommen, also wirklich bei dem D in next() / bzw. list.getElem(). Was du jetzt anschließend machst ist, list=list.getNext(); <-- getNext von D ist aber null, d.h. in
Code:
list
steht jetzt [c]null[/c] , der Iterator läuft aber natürlich erst einmal noch weiter, und fragt innerhalb der Schleife natürlich wieder erneut hasNext() auf ...und genau an der Stelle kracht es dann natürlich da du dort
Code:
list.getNext()
aufrufst(wie bereits erwähnt ist list aber null 😀 )
Ich hoffe ich hab`s jetzt einigermaßen verständlich erklären können.
 
Ok, jetzt hab ich es letztendlich verstanden. Danke für Deine Hilfe.

Ich hab vielleicht noch ne kurze Frage an Euch. In meiner Klasse MyIterator ist noch eine Methode
remove(); . Ich hab versucht, diese Methode auch zu überschreiben :

Java:
	public void remove() { 
		 list = list.getNext();
	}

Java:
                        while(iter.hasNext()){  
			
			String s = iter.next();
		      
			    if(s=="B")
			         iter.remove();
			  
			    else System.out.println(s); 
			}

Ergebniss : S D
Ich weiß schon wo der Fehler liegt, aber hab Schwierigkeiten, um ihn zu beseitigen.
Also: Das Element wird in s gespeichert, dann mit B verglichen, wenn s ungleich "B" ist, wird das
Element (s ) ausgegeben. Aber wenn s und "B" gleich sind, wird dann "B" gelöscht. Meine Methode
überspringt das Element B und der Zeiger zeigt auf "C". Jedoch wieder kommt der Aufruf iter.next();
und der Zeiger zeigt auf D und D wird überprüft und zurückgegeben. (Mit C passiert nicht)
Ist meine Methode remove(); noch nicht optimal oder liegt der Fehler irgendwoanders?

Vielen Dank im Voraus!!!
 
Also bei einem remove, musst du ja auch wirklich das Element löschen aus der Liste.
Removes from the underlying collection the last element returned by the iterator (optional operation). This method can be called only once per call to next.
D.h. du musst einfach die Referenzen etwas "umbiegen" 🙂
Wenn du B löschen willst in deinem Beispiel, musst du natürlich S.next auf C setzen. Das ganze wäre sicherlich einfacher, wenn man sich für die "Nodes" eine eigene Klasse schreibt, die das eigentliche Element und die Referenz auf den nächsten Knoten hält.
Die Liste merkt sich dann evtl. nur den ersten Knoten und den "Akutellen" evtl. oder so.

Wie man jetzt das remove dann genau umsetzt, müsste man sich dann eben überlegen.
Du könntest eine remove(int index), remove(Object obj) Methode o.ä. in der "Liste" implementieren(die dann eben korrekt das Objekt/Node löschen und die Referenzen umbiegen), der Iterator ruft dann einfach diese Methode auf....

Also ums nochmal zusammen zu fassen: Du musst S sagen, dass sein Nächster jetzt C ist =) (und das eben nicht nur für das momentane Iterieren)
 
Beim selbstprogrammieren von Listen/Collections, die Referenzen verbiegen, würde ich mir immer ein Bild mit Papier und Bleistift malen, das den Zustand wiedergibt. Prinzipiell ist das ananlog zum Arbeiten mit Pointern.
Du malst Kreise für Elemente und Pfeile, die den Referenzen entsprechen zu jeder Methode. Jede Aktion, d.h. neuer Kreis, neue Pfeil, Pfeil löschen etc. muß sich in einer oder mehreren Programmzeilen wiederspiegeln. Das funktioniert sehr einfach und hat den Vorteil, daß Du beim Erstellen jeder Methode den Überblick behältst.
 
Ok, danke. Mir ist noch etwas aufgefallen. Normalweise zeigt der Zeiger einer Liste auf das erste Element.
Dann verwendet man die Rekursion next.methode() und der Zeiger zeigt auf das zweite Element.

Ist es möglich den Zeiger so einzustellen, dass er sofort auf das letzte Element zeigt?Und dass man mit
next.prev das vorletzte Element erreichen kann u.s.w. bis das erste Element erreicht wurde.
Wie sollte der Konstruktor aussehen?

Vielen Dank im Voraus!
 
Also ich hab oben ja schon mal versucht anzudeuten, dass es wohl besser ist, wenn man eben nicht nur MyList Objekte hat, sondern eben nur eine Liste, die eben "Listelemente" beinhaltet. Die wiederum halten
a) Das Element
b) die Referenz auf den Nachfolger / null
c) doppelt verkettet = auch den Vorgänger (wenn es das ist worauf du hinaus willst) (Liste (Datenstruktur) ? Wikipedia)

Was du jetzt mit Rekursion meintest, k.a. das verwirrt mich 😉
Vllt. hilft es dir ja auch mal, kurze fertige, knappe simple Listimplementierungen anzuschauen, wie es dort gelöst wurde (z.B. Java Tips - Linked List Implementation in Java, wobei das direkt der erste Fund war bei google, gibt sicherlich bessere. Das worauf ich hinaus wollte ist, dass es eben dort eine Klasse LinkedList und eine ListNode gibt)
 

Zurück
Oben