Iterator über nested HashMaps

Pastafari

Mitglied
Hallo,

ich habe hier ein Problem mit einem Iterator über verschachtelte HashMaps.

Meine äussere Map hat die Struktur: HashMap<String, HashMap<String, String>>
die innere enthält nur Strings.

Zu Testzwecken habe ich meine Map mit sechs Werten befüllt.

Ich habe aber ein Problem mit meinem Iterator. Genauer bei meiner hasNext()-Methode. Anstatt sechs mal true zurückzugeben tut diese das in einer Endlosschleife.

Java:
@Override
public boolean hasNext() {
	while(iteratorAussen.hasNext()) {
		eintraege= mapAussen.values();
		iteratorInnen= eintraege.iterator();
		while(iteratorInnen.hasNext()) {
			System.out.println("foo");
			return true;
		}
	}
	return false;
}

Der iteratorAuusen läuft über das entrySet der äusseren Map, die Ausgabe "foo" ist nur zum Testen drinnen.

Kann mir da eventuell wer auf die Sprünge helfen?
 
Bei jedem aufruf von "iterator()" wird ein NEUER Iterator erzeugt. Der ist nie am Ende.

Man muss sich immer den aktuellen Iterator zwichenspeichern. Das ist ein bißchen frickelig, insbesondere schwierig wenn man das in der JavaDoc beschriebene Verhalten von Iteratoren einhalten will. Kannst ja mal schauen und sagen, wenn's nicht klappt. Als Inspiation kann vielleicht das von Landei in http://www.java-forum.org/allgemeine-java-themen/135448-listiterator-ueber-mehrere-arrays.html gepostete dienen, muss man mal genauer schauen
 
Danke für den Hinweis. Jetzt habe ich ihn immerhin soweit, dass hasNext() nur noch vier mal true zurückgibt. Das sind zwar immer noch zwei mal zu wenig, aber besser als unendlich oft.

Java:
@Override
public boolean hasNext() {
	if(iteratorAussen.hasNext()) {
		while(iteratorSave.hasNext()) {
			eintraege= iteratorSave.next();
			System.out.println(eintraege.toString());
			return true;
		}
	}
	return false;
}

Ich bekomme jetzt immerhin in "eintraege" HashMaps aus der äusseren Map geliefert. Da kann ich morgen hoffentlich mit weiterarbeiten 🙂
 
Bei Iteratoren müssen in der Schleife jeweils genau einmal ein hasNext()- und ein next()-Aufruf drinnen sein.
  • Vergisst man das next() gibt hasNext() immer true zurück, wenn mindestens ein Element enthalten ist, weil der Pointer nicht weiter bewegt wird.
  • Macht man öfter als einmal next(), fliegt irgendwann eine NoSuchElementException.
Ersteres war/ist das Problem in Deinen Schleifen. Außerdem kommt es mir merkwürdig vor, dass Deine Methode nicht mit lokalen Variablen oder Parametern für die Iteratoren arbeitet. Bei wiederholtem Aufruf stehen die Pointer der Iteratoren "irgendwo" und es kommt bestimmt nie das raus, was Du haben willst. Zumindest bei der inneren Schleife ist das aktuell ein Problem.

Ich ahne, dass Du sowas wie eine verschachtelte oder "tiefe" Iteration bauen willst. Ist das so?
 
Ja, sowas hatte ich schonmal in viel allgemeinerer Form gebastelt, kann ggf. mal schauen ob ich das heute abend ausgraben kann... falls du bis dahin keine Lösung findest...
 
Ich hatte mich gestern Abend zu früh gefreut. Meine hasNext() Methode hat zwar meinen Teststring in der richtigen Anzahl ausgegeben, hat aber doch nicht oft genug true zurückgegeben um damit next() oft genug aufgerufen wird.

Die Variablen meiner Iteratoren sind bei mir der Iteratorklasse zugehörig.

Wenn ich next() in meiner hasNext() aufrufe, wird das Ergebnis verfälscht, da der Pointer dann schon einen Schritt weiter geht. Wenn jetzt eine den Iterator aufrufende Methode hasNext() & next() aufruft wäre mein Pointer ja bereits zwei Felder weiter.
 
Wenn ich next() in meiner hasNext() aufrufe, wird das Ergebnis verfälscht, da der Pointer dann schon einen Schritt weiter geht. Wenn jetzt eine den Iterator aufrufende Methode hasNext() & next() aufruft wäre mein Pointer ja bereits zwei Felder weiter.
Du siehst, man muss sich bei der Benutzung von Iteratoren an ein paar Regeln halten und man verliert bei verschachtelten Iteratoren offensichtlich schnell mal die Übersicht. Deswegen hatte ich in meinem letzten Post auch etwas die Richtung und den Zweck abgefragt, den Du damit verfolgst.
 
Ich habe es jetzt so hinbekommen, dass ich in meiner hasNext() nur abfrage ob der äussere oder der innere Iterator noch ein hasNext() besitzt. Jetzt muss ich zwar vor dem ersten Aufruf von hasNext() prüfen ob es überhaupt eine Map gibt über die iteriert werden kann, aber ich finde es besser als meine Lösungsversuche mit Schleifen.

Den Rest habe ich über meine next() Methode gelöst. Es ist nicht wirklich schön geworden, aber mein Iterator läuft und er läuft auch schneller als gefordert wurde 😀
 

Zurück
Oben