Fehler beim Erweitern eines zweidimensionalen Arrays

  • Antworten:28
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 213

27.01.2016, 17:05:44 via Website

Ich möchte ein zweidimensionales Array um einen "Datensatz" erweitern. Dem Array soll also eine neue, weitere Zeile hinzugefügt werden. Jede Zeile besteht aus drei Spalten.

Beim Hinzufügen greife ich von einem DialogFragment aus auf das Array zu, das sich in der ActivityMain befindet. Hier die UpdateProzedur, die das Array aktualisieren möchte:

public void UpdateArray2DInfosGesamt(String iD, String info,String father){
        //das 2dimensionale Array arr2DInfosGesamt wird mit dem neuen Datensatz aktualisiert
        int arraySize;
        String teil;

        MainActivity mainActivity = new MainActivity();
        arraySize = mainActivity.arr2DInfosGesamt.length;

        mainActivity.arr2DInfosGesamt[arraySize][0] = iD;
        mainActivity.arr2DInfosGesamt[arraySize][1] = info;
        mainActivity.arr2DInfosGesamt[arraySize][2] = father;



    }

Folgende Fehlermeldung erscheint:
image

Hängt der Fehler vielleicht mit der folgenden Deklaration in der MainActivity zusammen?:

static String [][] arr2DInfosGesamt;

Antworten
  • Forum-Beiträge: 2.492

27.01.2016, 18:41:53 via App

Mit .length erhälst du die Länge. Ein Array zählt aber von 0 bis Länge-1. Also hast du ein Array mit 5 Elementen ergibt .length = 5. Das letzte Element ist aber an Position 4. (das erste an 0).
Deshalb die indexoutofbounds.

Falls du dein Array wirklich erweitern willst. Also von Länge 5 auf 6 zum Beispiel müsstest du es neu initialisieren und alles rüber kopieren. Dafür wäre dann eine ArrayList besser gedacht. Die kann während der Laufzeit dynamisch erweitert werden.

— geändert am 27.01.2016, 18:44:51

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

27.01.2016, 19:08:07 via Website

Das nullbasierte Array habe ich schon berücksichtigt.

Wenn length zB 32 liefert, sind das die Einträge von 0 bis 31. Folglich haut es hin, wenn das nächste freie Element mit length (also 32) angesprochen wird.

Es wird - wie Du wohl schon richtig andeutest - damit zu tun haben, dass man das Array nicht erweitern kann, sondern neu initialisieren muss. Programmtechnisch würde das einen Zeitverlust bedeuten (bei zB 1500 Datensätzen).

Vielleicht kann ich ja doch noch auf eine Arraylist zugreifen. Ich glaube, dass ich diesmal keine Arraylist verwendet habe, weil ich nicht heraus bekam, wie man eine zweidimensionale Arraylist erstellen kann. Weißt Du, ob das geht?

Dir jedenfalls Danke!

— geändert am 27.01.2016, 19:24:23

Antworten
  • Forum-Beiträge: 213

27.01.2016, 19:16:29 via Website

Mir ist doch noch eine Idee gekommen.

Was wäre denn, wenn ich das Array von vornherein so groß erstelle, dass ich noch Platz zum Einfügen hätte?

Im Augenblick wird es ja so deklariert:

static String [][] arr2DInfosGesamt;

Ich könnte ja hingehen, und stattdessen folgendes schreiben:

static String [3000][3] arr2DInfosGesamt;

Kann ich ja mal ausprobieren. Sieht aber irgendwie nach einer Notlösung aus :-).

Antworten
  • Forum-Beiträge: 8.173

27.01.2016, 20:14:18 via Website

Mach dir statt des "Satz" für das mehrdimensionale Array eine kleine (interne) Klasse und nimm dann die ArrayList oder was anderes passendes.
Das ist flexibler....und mehr objectorientiert.

if all else fails, read the instructions.

Frank Rudolf

Antworten
  • Forum-Beiträge: 359

28.01.2016, 09:39:02 via Website

Und hier noch ein Besiel...

public class Info{
        private int id ;
        private String info;
        private Info father;

    public Info(){
        super();
    }

    public Info(int id, String info, Info father) {
        this();
        setFather(father);
        setId(id);
        setInfo(info);
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
    public Info getFather() {
        return father;
    }
    public void setFather(Info father) {
        this.father = father;
    }


}

Und nutzt es dann mit:

ArrayList<Info> infolist = new ArrayList<Info>();
infolist.add(new Info(123,"",null));

Frank Rudolf

Antworten
  • Forum-Beiträge: 605

28.01.2016, 09:48:48 via Website

Genau so wie Fabian würde ich es auch machen. So bist du sowohl beim hinzufügen neuer "Datensätze" in die ArrayList, als auch beim ändern von bestehenden Daten sehr flexibel.

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

28.01.2016, 09:57:14 via Website

Mach dir statt des "Satz" für das mehrdimensionale Array eine kleine
(interne) Klasse und nimm dann die ArrayList oder was anderes
passendes. Das ist flexibler....und mehr objectorientiert.

Das klingt gut. Für mich bleibt aber noch immer - aufgrund meines Anfängerstatus in Android(?) - das Problem, mit einer zweidimensionalen Arraylist zu arbeiten.

Kannst Du mich vielleicht auf ein Beispiel verweisen?

Antworten
  • Forum-Beiträge: 605

28.01.2016, 10:00:49 via Website

Hallo Frank,

die ArrayList an sich ist weist nur eine Dimension auf, und zwar dein selbst erstelltes Objekt.
Dieses Objekt wiederum verfügt über die drei Variablen ID, info und father.

Das Beispiel oben von Fabian ist schon sehr gut.

Henrik

— geändert am 28.01.2016, 10:00:58

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

28.01.2016, 10:08:14 via Website

Danke Fabian für das ausgeführte Beispiel. Du greifst scheinbar die Idee von Klaus auf. Gefällt mir gut.

Ich hoffe nur, dass ich dann nicht dieselben Aktualisierungsprobleme beim Hinzufügen neuer Elemente habe wie bei einem "normalen" 2D-Array. Aber ich vermute, dass es so gehen dürfte.

Hintergrund:
ich möchte ja gelegentlich eine Datenmenge aus mehreren Tausend Elementen durch das Hinzufügen neuer Datensätze aktualiseren. Und dies soll zudem von einem Fragment aus geschehen (falls notwendig).

Seit gestern beschäftige ich mich mit der Datenübergabe zwischen Fragments und Activities (Callbacks etc.) als Alternativlösung. Vielleicht kann ich darauf sogar verzichten mit so einer eigenen ArrayListKlasse.

Eine Detailfrage noch an Dich. Wofür brauche ich das this im folgenden Code?

public Info(int id, String info, Info father) {
        this();
        setFather(father);
        setId(id);
        setInfo(info);
    }

— geändert am 28.01.2016, 10:09:04

Antworten
  • Forum-Beiträge: 213

28.01.2016, 10:12:05 via Website

Danke auch Dir, Henrik!

Ich habe den Verdacht, dass ich den Weg der eigenen ArraylistKlasse gehen werde.

Mal sehen, welche Probleme dann auftauchen :). Aber lehrreich ist das wohl schon :).

Antworten
  • Forum-Beiträge: 2.492

28.01.2016, 10:22:36 via Website

Das this() ruft den Konstruktor

public Info(){
    super();
}

auf. Dieser ruft mit super() den Konstruktor der Superklasse auf. Falls du deine Info-Klasse also von nichts anderem ableitest ist das this nicht notwendig.

— geändert am 28.01.2016, 10:24:37

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

28.01.2016, 10:35:48 via Website

Mir fehlt im Augenblick noch meine Vorstellungskraft :).

Nehmen wir mal an, dass ich die ArrayList bereits mit vielen Elementen gefüllt habe.
ZB könnte das Hinzufügen des 1000. Elements so aussehen:

infolist.add(new Info("999","Hier steht die eigentliche Info", "4");

Wie greife ich dann bei Bedarf auf den Inhalt dieses 1000. InfoElements zu?

Übrigens:
nicht wundern, dass ich (in Abwandlung des FabianCodes) für das erste und dritte Element Strings nehme! Das ist in der Tat ungewöhnlich. Es liegt daran, dass die Daten aus einer Textdatei kommen. Natürlich könnte ich die noch umwandeln. Aber wer weiß, was für Probleme sich noch daraus entwickeln? Letztendlich muss ich nämlich auch noch eine Art Synchronisierung schaffen (ca. zwei Versionen dieser "Datenbank"; eine läuft derzeit unter Access, die andere soll auf Android laufen).

Nochwas:
Den FabianCode würde ich so modifizieren:

private String id ;
private String info;
private String father;

Das sind also die MemberVariablen der Info-Klasse.
Father ist nur die ID des übergeordneten Info-Elements. Hier herrscht das Prinzip der verketteten Liste.

Beispiel:
3; Europa;0
4;Italien;3
5;Irland;3
7;Dublin;5
23;Rom;4

— geändert am 28.01.2016, 10:47:52

Antworten
  • Forum-Beiträge: 2.492

28.01.2016, 10:40:13 via Website

Info info = infolist.get(999);
String element1 = info.getId();
String element2 = info.getInfo();
String element3 = info.getFather();

Du holst dir also das Element aus der ArrayList und kannst dann die getter-Methoden des Objektes nutzen um die Daten auszulesen.
Falls du nur eins benötigst (das könntest du auch bei allen Elementen so machen, finde ich aber persönlich unschöner) könntest du auch kurz so machen:

String element1 = infolist.get(999).getInfo();

— geändert am 28.01.2016, 10:41:09

Frank Rudolf

Antworten
  • Forum-Beiträge: 605

28.01.2016, 10:41:33 via Website

Entweder du entnimmst der Arraylist das Objekt an entsprechender Stelle oder du durchsuchst es mit einer Schleife nach einem Objekt, was eine bestimmte Eigenschaft (ID, Info oder father) aufweist.

Die einzelnen Variablen aus den Objekt entnimmst du dann mit dem ".getID()" oder ".getInfo()" oder ".getFather()".

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

28.01.2016, 10:53:40 via Website

Danke für Eure super Hilfe!

Werde also mit Umbaumaßnahmen beschäftigt sein. Von Ergebnissen oder Problemen dabei werdet ihr schon hören :)

Antworten
  • Forum-Beiträge: 213

28.01.2016, 12:38:05 via Website

Zwischenbericht:

Das Adden mit der ListArrayKlasse funktioniert :).

Als nächstes muss ich mich mit der Aktualisierung des ListViews befassen.

Antworten
  • Forum-Beiträge: 213

28.01.2016, 13:07:55 via Website

Hier ein Beispiel für eine notwendige Anpassung des Codes. Die ArrayList-Klasse heißt nun textFile.

 for(int i=0; i< textFile.size(); i++) {
        if(textFile.get(i).getId().equals(father))
            {
                TextView textView = (TextView) findViewById(R.id.textViewKopf);
                textView.setText(textFile.get(i).getInfo());
            }
        }

@Lars:
Es ging nur die "unschöne" Langversion.

textFile.getInfo();

geht zB nicht. Beim Setzen des Punktes hinter textFile und Aufklappen der IntelliSense-Möglichkeiten erscheinen in dieser Kurzfassung auch gar nicht die Methoden der Klasse. Seltsam!

— geändert am 28.01.2016, 13:10:35

Antworten

Empfohlene Artikel