java.lang.IndexOutOfBoundsException bei verschachtelter ArrayList

Hackepeter

Aktives Mitglied
Servus,

habe leider ein Problem mit meiner Anwendung. Ich verwende eine verschachtelte ArrayList, also eine ArrayList in einer ArrayList, weil ich ein zwei-dimensionales Array von einem Objekt benötige.

Ich beschreibe ein Spielfeld quasi wie eine Tabelle. Zunächst fülle ich eine Zeile mit Objekten (das wäre die innere ArrayList:

Java:
temp.add(spielkarte);

Wenn eine Zeile voll ist, schreibe ich die temporäre ArrayList in das Klassenattribut (Hauptarray) des Spielfelds und leere es anschließend:

Java:
if((i + 1) % anzahlSpalten == 0 && i != 0){
	            spielfeld.add(temp);
	            temp.clear();
	        }

Jetzt versuche ich in einer anderen Methode auf die einzelnen Elemente zuzugreifen und erhalte eine IndexOutOfBoundsException: Index: 0, Size: 0:

Java:
for(int i = 0; i < anzahlZeilen; i++)
	    {
	        for(int j = 0; j < anzahlSpalten; j++)
	        {
	            id = spielfeld.get(i).get(j).getId();
	            ...
	        }
	    }

Beim Debuggen habe ich gesehen, dass sämtliche Elemente auf Null stehen. Nun bin ich mir nicht sicher, ob man sowas im Debugger einfach nicht sehen kann, oder ob da was schief gelaufen ist. Hat es vielleicht etwas damit zu tun, dass ich das temporäre Array wieder leere? Eigentlich ja nicht, oder? Die Objekte aus dem temporären Array müssten ja jetzt eigentlich im Hauptarray stecken.

Ich komm leider auch nicht wirklich auf eine Lösung.

Ich hoffe mir kann jemand helfen.

Danke im Voraus!
 
Deine Liste ist leer. Normalerweise schreibt man Iterationen durch Arrays und Listen so:
Java:
for (int i = 0; i < spielfeld.size(); i++) {
    List<Foo> reihe = spielfeld.get(i);
    for (int j = 0; j < reihe.size(); j++) {
        // ...
    }
}
Wenn du aber den Index gar nie benötigst, kannst du auch so durchiterieren:
Java:
for (List<Foo> reihe : spielfeld) {
    for (Foo element : reihe) {
        // ...
    }
}
 
Du hast eine ArrayList in einer ArrayList, und dann hast du einen Typ, der in dieser verschachtelten ArrayList steht.
Wenn du eine ArrayList mit diesem Typ erzeugst und diese ArrayList in die Hauptliste steckst, dann darfst du diese nicht leeren. Schließlich werden nur Referenzen übergegeben und keine ganzen Objekte.
Deine Variable
Code:
temp
und der Index in deiner Hauptliste zeigen also auf das gleiche Objekt. Wenn du jetzt eine der beiden Refernezen verwendest, um das Objekt zu manipulieren, wird das an beiden Enden sichtbar.

Um das vielleicht bisschen verständlicher zu machen:

Java:
List<List<String>> list = new ArrayList<>();
List<String> temp = new ArrayList<>(); // "temp" ist so gesehen keine Liste, sondern nur eine Referenz auf eine Liste. "new ArrayList<>();" erzeugt eine Liste und "temp" zeigt auf diese. Später kann man mit "temp = otherList;" die Referenz ändern, damit bleibt aber die ArrayList der rechten Seite unverändert.
temp.add("Hallo"); // nun wird in die rechte ArrayList, die wir erzeugt hatten, auf die temp zeigt, Sachen eingefügt.
temp.add("Welt");
list.add(temp); // es wird nun eine Referenz übergeben. Index 0 der Liste, auf die "list" zeigt, zeigt nun auf die gleiche Liste, auf die auch "temp" zeigt.

Auf den ersten Blick bisschen verwirrend, aber wenn man sich das öfter anguckt und einige Beispiele schreibt, wird das klarer.
 
Zuletzt bearbeitet:
Ah, verstehe. Und gibt es die Möglichkeit, die temporäre Liste als Kopie zu übergeben? Bei C++ musste ich immer angeben, dass ich einen Pointer übergebe.
 
Deswegen?
[c]temp.clear();[/c]

Du fügst ja sogar immer die gleiche Liste hinzu. Was du vermutlich möchtest kannst du zB so umsetzen:
Java:
if((i + 1) % anzahlSpalten == 0 && i != 0){
                spielfeld.add(new ArrayList(temp));
                temp.clear();
            }


[OT]
...man man, bin ich wieder langsam gewesen 😀 [/OT]
 
Dazu müsstest du den Code von Fant benutzen...
Aber Vorsicht sei geboten... Ich sehe den Sinn hinter dem Codeschnipsel nämlich nicht. Du kopierst die ganze Liste, um die Liste später zu löschen? Das ist einmal fast O(n) und einmal O(1).
Ich glaube, was du willst, ist eher das:
Java:
spiefeld.add(temp);
temp = new ArrayList<>();
Bewirkt genau das gleiche, ist aber einmal fast O(1) und einmal O(1).
 
Was bedeutet dieses O(1)? Ja, genau das habe ich gesucht. Ich werde es mal ausprobieren, aber ich sehe jetzt schon, dass dort der Fehler begraben liegt.
 

Neue Themen


Zurück
Oben