ArrayList Rückgabewerte aus einer Funktion

MiMa

Top Contributor
Hi,
ich möchte mehrere Datein verarbeiten, die sich auch in Unterverzeichnissen befinden können.
Daher muss ich das ganze dann mit einer rekursiven Funktion realisieren.
Die ganze Verarbeitung der Dateien habe ich dann mitten in die Rekusion gebaut und am Ende wurde das ganze unübersichtlich.
Daher habe ich mir überlegt, zuerst eine Dateiliste erstellen zu lassen, die alle Datensätze rekursiv sammelt und dann nacheinander abarbeitet.
Da ich nicht weiss wie viele Datensätze es sein werden, kann ein Array nicht verwendet werden. Daher habe ich mich entschieden eine ArrayList zu nehmen, an diese Datensätze angehangen werden können.
Meine Funktion "dateiListeMR" benötigt einen String Parameter mit dem Pfad des Quellverzeichnisses. Zurück gegeben wird dann eine ArrayList mit den gesammelten Dateien als File.
Java:
// erstellt eine Dateiliste mit Rekursiver Verzeichnistiefe
    public ArrayList dateiListeMR(String quellOrdner) {

        //Dateipfad zum Quellverzeichnis erstellen
        File pfad = new File(quellOrdner);

        // File Array mit allen Dateien aus dem QuellVerzeichnis füllen
        File[] normaleDateiListe = pfad.listFiles();
        ArrayList<File> rekursiveDateiListe = new ArrayList<File>();

        // Wenn das Verzeichnis nicht leer ist, dann Inhalt verarbeiten
        if (normaleDateiListe != null) {
            // Wenn die normaleDateiListe nicht leer ist, Einträge verarbeiten
            // for earch Schleife, arbeitet jede Zeile des Arrays ab
            for (File inhaltListe : normaleDateiListe) {
                // Verarbeitet den Inhalt der Dateiliste
                if (inhaltListe.isFile()) {
                    // Wenn der Inhalt eine Datei ist, an die rekursiveDateiListe anhängen
                    rekursiveDateiListe.add(inhaltListe);
                } else {
                    // Wenn ein Verzeichnis, dann Rekursiver Funktionsaufruf
                    dateiListeMR(inhaltListe.toString());
                } // Rekursiver Funktionsaufruf
            } // Verarbeitet den Inhalt der Dateiliste
        } // Wenn die Dateiliste nicht Leer ist

        // Rekursive Dateiliste in der Konsole ausgeben
//       for (int i = 0; i < rekursiveDateiListe.size(); i++)
//       System.out.println(rekursiveDateiListe.get(i));
     
       return rekursiveDateiListe;
    } // dateiListeMR
Die Funktion an sich arbeitet korrekt, denn ich erhalte genau 10 Datensätze, die sich in meinen Quellverzeichnis mit Unterverzeichnissen befinden.
Verwendet wird meine Funktion durch diesen Aufruf
Java:
ArrayList<File> dateiListe = new ArrayList<File>();
        dateiListe = dateiObjekt.dateiListeMR(dateiObjekt.getQuellOrdner());
        System.out.println("Anzahl der Datensätze in der Liste " + dateiListe.size());

        for (int i = 0; i < dateiListe.size(); i++) {
            System.out.println(dateiListe.get(i));
        }
Ein Problem scheint in der zurück gegebenen ArrayListe, in dem sich dann anscheinend nur 2 Dateien befinden. Und zwar sind das diese, die im root des Quellverzeichnisses sind.
Es fehlen alle Dateien in den Unterverzeichnissen.
Aber die ArrayList wurde vollständig erstellt. Innerhalb der Funktion wurde die ArrayListe ausgegeben und war mit 10 Datensätzen vollständig.
Nach der Übernahme der ArrayList habe ich die Datensätze nochmal zählen lassen und auch ausgegeben. Es waren dann nur noch 2 Datensätze??

Ich selbst kann den Fehler nicht finden und wäre für Hilfe Dankbar.

Vielen Dank
M
 
Zuletzt bearbeitet:
Habe jetzt die ArrayListe in ein Array umgewanelt und ein paar Konsolenausgaben gemacht.
Anscheinend habe ich ein Problem in der Rekursion?
 
Du musst Daten, die zwischen den Funktionsaufrufen der Rekursion geteilt werden müssen, über eine gemeinsame Variable teilen. Oder du benutzt statt solch einer Variable geschickt den return-Wert auf dem Call-Stack und bastelst aus diesen Teilstücken die Ergebnisliste.
 
Rekursion ist so eine Sache für mich, da muss ich alles mal wieder bis auf das kleinste herunter.
Habe jetzt noch mal einen neuen Versuch gemacht, in der ich alle Dateipfade auf die Konsole ausgebe.
Die rekursive Funktion
Java:
// Erstellt eine Dateiliste mit einer Rekursiven Verzeichnistiefe
    public static void erstelleDateiListe(File[] dateiListe) throws IOException{
        // Durchlaufen der übergebenen Dateiliste
        for (int i = 0; i < dateiListe.length; i++) {
            // Wenn der Datensatz eine Datei ist, auf die Konsole ausgeben
            if (dateiListe[i].isFile()) {
                System.out.println(dateiListe[i].getCanonicalPath());
            } // if
            else if (dateiListe[i].isDirectory()) {
                // Wenn der Datensatz ein Verzeichnis ist, Inhalt des neu gefundenen
                // Verzeichnisses als Parameter in die rekursive Funktion übergeben
                erstelleDateiListe(dateiListe[i].listFiles());
            } // else-if
        } // Durchlaufen der Dateiliste
    } // erstelleDateiListe
Aufruf der Funktion
Java:
// Erzeugt ein Datei-Objekt und schreibt das QuellVerzeichnis über
        // den Konstruktor direkt in die Instanzvariable quellOrdner
        Datei dateiObjekt = new Datei(pfadQuelle);
       
        // Quellverzeichnis in ein File-Objekt umwandeln
        File quellVerzeichnis = new File(dateiObjekt.getVerzeichnisPfadQuelle());
               
        // Aufruf der Rekursiven Funktion
        Datei.erstelleDateiListe(quellVerzeichnis.listFiles());
Das hat jetzt wieder geklappt.
Die Frage ist jetzt wie ich gefundene Dateien in eine Array Liste hinzufügen kann?
Wenn ich jetzt bei der Funktion zusätzlich den Parameter für ein ArrayList hinzufüge und die sich selbst aufruft, wird dann immer die gleiche ArrayList mitgeführt?
Wird dort tatsächlich mit der .add Funktion addiert?
 
Wenn ich jetzt bei der Funktion zusätzlich den Parameter für ein ArrayList hinzufüge und die sich selbst aufruft, wird dann immer die gleiche ArrayList mitgeführt?
Richtig. Das ist die gemeinsame Variable, die ich erwähnt habe.
Die Frage ist jetzt wie ich gefundene Dateien in eine Array Liste hinzufügen kann?
Wird dort tatsächlich mit der .add Funktion addiert?
Genau, du fügst mit add(T elem); zur Liste hinzu.
 
Die Funktion sieht mittlerweile so aus
Java:
// Erstellt eine Dateiliste mit einer Rekursiven Verzeichnistiefe
    public static void erstelleDateiListe(File[] dateiListe,
            ArrayList<File> sammelListe) throws IOException{
        // Durchlaufen der übergebenen Dateiliste
        for (int eintrag = 0; eintrag < dateiListe.length; eintrag++) {
            // Wenn der Datensatz eine Datei ist, auf die Konsole ausgeben
            if (dateiListe[eintrag].isFile()) {
                System.out.println(dateiListe[eintrag].getCanonicalPath());
                sammelListe.add(dateiListe[eintrag]);
            } // if
            else if (dateiListe[eintrag].isDirectory()) {
                // Wenn der Datensatz ein Verzeichnis ist, Inhalt des neu gefundenen
                // Verzeichnisses als Parameter in die rekursive Funktion übergeben
                erstelleDateiListe(dateiListe[eintrag].listFiles(), sammelListe);
            } // else-if
        } // Durchlaufen der Dateiliste
    } // erstelleDateiListe
Es funktioniert die Anzahl der Einträge kann ich nun auch ausserhalb der Funktion abrufen.
Die Anzahl der Einträge stimmt.
Vielen Dank für die Hilfe.
MiMa
 
Zuletzt bearbeitet:
  1. Deine sammelListe ist an die Instanz gebunden. Die Funktion erstelleDateiListe ist aber static. Du kannst aus dem statischen Kontext auf keine Instanzvariablen zugreifen, weil du von Natur von static aus keinen this-Pointer hast.
  2. dateiListe ist ein Array. Arrays kannst du nur per index auslesen. dateiListe[0], dateiListe[1] ... dateiListe[n]. Du könntest über das array iterieren und eintrag für eintrag der Liste hinzufügen oder aber das array in eine Liste überführen, weil List<E> folgende Funktionen bietet:
    boolean add(E e)
    void add(int index, E element)
    boolean addAll(Collection<? extends E> c)
    boolean addAll(int index, Collection<? extends E> c)
 
Deine sammelListe ist an die Instanz gebunden. Die Funktion erstelleDateiListe ist aber static. Du kannst aus dem statischen Kontext auf keine Instanzvariablen zugreifen, weil du von Natur von static aus keinen this-Pointer hast.
Was in diesem Kontext völliger Unsinn ist, da es sich um einen Parameter handelt.
dateiListe ist ein Array. Arrays kannst du nur per index auslesen. dateiListe[0], dateiListe[1] ... dateiListe[n]. Du könntest über das array iterieren und eintrag für eintrag der Liste hinzufügen oder aber das array in eine Liste überführen, weil List<E> folgende Funktionen bietet:
boolean add(E e)
void add(int index, E element)
boolean addAll(Collection<? extends E> c)
boolean addAll(int index, Collection<? extends E> c)
Auch hier verstehe ich den Sinn nicht, da auf dateiListe nur lesend zugegriffen wird
 
Die Dateiliste habe ich in der Klasse Datei definiert.
Java:
private ArrayList<File> sammelListe;
Ebenfalls habe ich in der Klasse Datei folgenden Konstruktor
Java:
// Konstruktor für Datei-Objekt mit Angabe des Quellverzeichnises
    public Datei(String verzeichnisPfadQuelle) {
        this.verzeichnisPfadQuelle = verzeichnisPfadQuelle;
        this.sammelListe = new ArrayList();
    }
Für das abrufen habe ich Methoden
Java:
public ArrayList<File> getSammelListe() {
        return sammelListe;
    }

    public void setSammelListe(ArrayList<File> sammelListe) {
        this.sammelListe = sammelListe;
    }
Abrufen funktioniert so
Code:
System.out.println("\nDie Gesammelte Liste enthält " + dateiObjekt.getSammelListe().size() + " Einträge");

Das auslesen der einzelnen Inhalte funktioniert auch
Java:
for (int ausgabe = 0 ; ausgabe < dateiObjekt.getSammelListe().size(); ausgabe++) {
            System.out.println(dateiObjekt.getSammelListe().get(ausgabe));
        }
 
Zuletzt bearbeitet:
@tommysenf Es traten die Probleme
- Zugriff auf Instanzvaraiablen aus einer static Funktion und
- wie bekomme ich Elemente aus einem Array in eine Liste auf
Was genau hab ich davon jetzt falsch erklärt? Wenn du in Sinnhaftigkeit oder Designaspekten helfen willst mach das doch gern.
 
Ich habe in meiner Klasse Datei in den Bauplan eine Instanvariable eingebaut und über den Konstruktor erzeugt. Ich kann damit innerhalb der rekusiven Funktion auf diese zugreifen.
Nachdem die Rekursive Funktion beendet ist, enhält diese dann alle Ergebnisse, auf die ich zugreifen kann. Zumindest funktioniert das Konstrukt bei mir. Ist das denn falsch?
Ein anderer Gedanke, der mir dann einfällt, den Parameter sammelListe wieder zu entfernen und innerhalb der Funktion die Sammelliste zu erstellen und alle gesammelten Einträge mit return zurück zu geben. Das hatte ich mit der ersten Version eigentlich vor, was aber nicht geklappt hat. Jeder neue Aufruf der Funktion würde dann immer eine neue sammelListe erzeugen. Ich hätte jetzt keine Ahnung wie ich das realisieren müsste damit ich eine Sammelliste erhalte, die dann zurück gegeben werden könnte.
 
Es traten die Probleme
- Zugriff auf Instanzvaraiablen aus einer static Funktion und
- wie bekomme ich Elemente aus einem Array in eine Liste auf
Ich kann keine Hinweis darauf finden, dass es in diesem Thread um eines der geschilderten Probleme geht. Ich kann ja noch nicht mal eine Instanzvariable erspähen, und auch keinen Versuch, eine Instanzmethode aus einer Klassenmethode heraus aufzurufen.
 
Ein anderer Gedanke, der mir dann einfällt, den Parameter sammelListe wieder zu entfernen und innerhalb der Funktion die Sammelliste zu erstellen und alle gesammelten Einträge mit return zurück zu geben. Das hatte ich mit der ersten Version eigentlich vor, was aber nicht geklappt hat. Jeder neue Aufruf der Funktion würde dann immer eine neue sammelListe erzeugen. Ich hätte jetzt keine Ahnung wie ich das realisieren müsste damit ich eine Sammelliste erhalte, die dann zurück gegeben werden könnte.

Wie ich schon schrieb musst du den Rückgabewert des rekursiven Aufrufs auch beachten. Also statt

Code:
                    // Wenn ein Verzeichnis, dann Rekursiver Funktionsaufruf
                    dateiListeMR(inhaltListe.toString());

musst du das Ergebnis auch mit in deine aktuelle Ergebnisliste mit aufnehmen:

Java:
                   // Wenn ein Verzeichnis, dann Rekursiver Funktionsaufruf
                    rekursiveDateiListe.addAll(dateiListeMR(inhaltListe.toString()));
 
Nach etwas Ruhe habe ich eine neue Version der Funktion.
Losgelöst von der Instanvariable mit einer Dateiliste von Typ ArrayList als Rückgabewert.
Java:
// Erstellt eine Dateiliste mit einer Rekursiven Verzeichnistiefe
    // Gibt eine Dateiliste als Rückgabewert zurück
    public static ArrayList<File> sammleDateiListe(File dateiListe, ArrayList<File> sammelListe) {
        IndexLogger.info("Funktion sammleDateiListe wurde aufgerufen");
        if (dateiListe == null || sammelListe == null) {
            IndexLogger.info("Die übergebene dateiListe, sammelListe ist leer");
            return null;
        } // if
  
        File[] suchListe = dateiListe.listFiles();
        IndexLogger.info("Eine suchListe für neu gefundene Verzeichnisse wurde erstellt");
        for (File eintrag : suchListe) {
            if (eintrag.isDirectory()) {
                IndexLogger.info("Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf");
                sammleDateiListe(eintrag, sammelListe);
            } // if
            else if (eintrag.isFile()){
            sammelListe.add(eintrag);
            IndexLogger.info("Die Datei wurde der sammelListe hinzugefügt");
            } // else-if
        } // for-Schleife
        IndexLogger.info("Die sammelListe wird zurückgegeben");
        return sammelListe;
    } // sammleDateiListe
Die Ausgabe auf der Konsole
Code:
Es wurde 10 Einträge gesammelt
N:\Dateien\datei10.txt
N:\Dateien\datei01.txt
N:\Dateien\02\datei02.txt
N:\Dateien\02\03\datei03.txt
N:\Dateien\02\03\04\datei04.txt
N:\Dateien\02\03\04\05\datei05.txt
N:\Dateien\06\datei06.txt
N:\Dateien\06\07\datei07.txt
N:\Dateien\06\07\08\datei08.txt
N:\Dateien\06\07\08\09\datei09.txt
BUILD SUCCESSFUL (total time: 0 seconds)
Das Logfile
Code:
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
INFO  rekursion.Datei    Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Der Eintrag ist ein Verzeichnis, Funktion ruft sich selbst auf
INFO  rekursion.Datei    Funktion sammleDateiListe wurde aufgerufen
INFO  rekursion.Datei    Eine suchListe wurde erstellt
INFO  rekursion.Datei    Die Datei wurde der sammelListe hinzugefügt
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
INFO  rekursion.Datei    Die sammelListe wird zurückgegeben
Ich hoffe, das ich es diesmal richtig gemacht habe.
Das Thema habe ich schon öfters versucht zu verarbeiten.
Danke
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben