# Problem in einer ArrayList



## vienna_devil (10. Dez 2010)

Hallo!

Also ich bin am Verzweifeln... Ich hab den Fehler bereits gefunden (bzw eingegrenzt), hab ich gerade überhaupt keinen Plan wie ich ihn beheben könnte!

Es geht um ein Rundenzeiten-Verarbeitungs-Programm für einen Lauf, das aus einer .txt Datei (simuliertes Log-File einer Zeitnehmung) gewisse Zeilen einliest, verarbeitet, sortiert und wieder ausgibt.
Aufbau der Zeilen ist dabei für das konkrete Problem jetzt irrelevant, wichtig ist nur ich bekomme alle Zeilen die auch wirklich einen Lauf (eine Runde) enthalten in Form "Run:Startnummer:Rundenzeit" bereits in einem Array zur Weiterverarbeitung.
Das Array ist dabei unsortiert und jeder Läufer (Startnummer) kann auch mehrfach (mehrere Runden) vorhanden sein.

(aus vorherigem Code entstandene variablen:
int anzahlLaeufe = 18
date ist ein beliebiger String
laenge ist ein double-Wert
)





```
//Einlesen der Runden-Anzahl als integer 
Scanner sc = new Scanner(System.in);
ArrayList<Lauf> laeufeList = new ArrayList<Lauf>();
int verschLaeufer = anzahlLaeufe;

for(int i = 0; i < anzahlLaeufe; i++)
                {
                    String[] temp = runs[i].split("\\:");
                    String name = temp[1];
                    double temporaryTime = Double.parseDouble(temp[2]) ;
                    boolean addRunner = true;

                    System.out.println(laeufeList.size());
                    for(int laufvar=0; laufvar < laeufeList.size(); laufvar++)
                    {
                        if(name.equals(laeufeList.get(laufvar).name))
                        {
                            laeufeList.get(laufvar).AddRunde(temporaryTime);
                            System.out.println("added time at " + laufvar);
                            addRunner = false;
                            verschLaeufer--;
                        }
                    }

                    if(addRunner && laeufeList.size() <= verschLaeufer)
                    {
                        //gibt der ArrayList welche die Läufer speichern soll, einen
                        //Eintrag LAUF, für den eben erstellten Läufer
                        laeufeList.add(new Lauf(name, date, laenge));
                        Lauf aktuellerLauf = laeufeList.get(i);
                        aktuellerLauf.AddRunde(temporaryTime);
                        System.out.println("added runner");
                    }
                }
```

also was hier passieren soll:
zuerst wird mal das Array der Läufe aufgespalten wird in seine Komponenten
dann wird in der for-Schleife (for(int laufvar=0; laufvar < laeufeList.size(); laufvar++)) überprüft ob der Läufer-Name (Startnummer) schon vorhanden ist
wenn ja - addet nur eine Zeit zu dessen ArrayList mit namen rundenZeitenList und gibt "time added" aus
wenn nein - addet den neuen Läufer und gibt "runner added" aus

jetzt kommen wir auch gleich zur Fehlermeldung:

```
Unexpected Error: java.lang.IndexOutOfBoundsException: Index: 16, Size: 10
```

die Ausgabe bis dahin sieht folgender maßen aus:

```
Datum = 12112010
Streckenlänge = 120.13
0
added runner
1
added runner
2
added runner
3
added runner
4
added runner
5
added runner
6
added runner
7
added runner
8
added runner
9
added time at 1
9
added time at 4
9
added time at 2
9
added time at 0
9
added time at 5
9
added time at 6
9
added time at 7
9
Unexpected Error: java.lang.IndexOutOfBoundsException: Index: 16, Size: 10
```

Der Fehler ist also anscheinend, das versucht wird weitere Läufer zu Adden, obwohl dafür keinen Informationen mehr vorhanden sind.
Das hab ich jetzt versucht durch die letzte if-Abfrage und die variable verschLaeufer zu lösen, aber offensichtlich ja ohne Erfolg...

Hab ich das Problem überhaupt richtig erkannt?
Was kann ich dagebgen tun?
Bitte um Hilfe!

lg


----------



## SlaterB (10. Dez 2010)

du könntest genauer werden, z.B. sagen in welcher Zeile die Fehlermeldung auftritt, falls du das weißt
(sollte in weiteren Zeilen der Fehlermeldung stehen),
auch die zugehörige Log-Datei zu posten hätte geholfen
(perfekt wäre, diese als String-Liste direkt in Quellcode eingefügt mit main-Methode vollständig zum Kopieren und Laufen lassen)

ich vermute den Fehler in Zeile 30 deines Codes, und zwar kamen erst Runner, dann Zeiten und nun ein neuer Runner, der 10.,
damit wird wieder das if von Zeile 25 bis 30 ausgeführt, der zehnte Runner eingefügt, dann aber
> Lauf aktuellerLauf = laeufeList.get(i);
i ist hier schon 16 weil ein paar Zeiten-Log-Zeilen dabei waren, in denen kein Runner eingefügt wurde,
i ist also als letzter Index der Liste nicht brauchbar

i brauchst du hier auch gar nicht, schreibe

```
laeufeList.add(new Lauf(name, date, laenge));
Lauf aktuellerLauf = laeufeList.get(laeufeList.size()-1); // ne Methode getLast(); gibts leider nicht
```
oder viel viel besser:

```
Lauf aktuellerLauf = new Lauf(name, date, laenge);
laeufeList.add(aktuellerLauf);
```
Listenzugriff gar nicht nötig


----------



## vienna_devil (10. Dez 2010)

vielen lieben dank für die schnelle hilfe!
funktioniert jetzt einwandfrei...

nur eines versteh ich noch nicht...
die liste soll im anschluss nach durchschnittsgeschwindigkeit sortiert werden - in meienr vorherigen hausübung lief das schon ohne probleme...
jetzt gehts aber garnicht mehr...

dazu hab ich jetz mal den ganzen code


```
import java.io.*;
import java.util.*;

public class TestClassFuerBSP3 {

    public static void main(String[] args) {

        int z=0, zaehler = 0, anzahlLaeufe = 0;
        String line;
        String date = "no date inserted";
        double laenge = 0;
        boolean ok = true;

        //Fehlerbehandlung falls kein file vorhanden ist
        try
        {
            try
            {
                //zeilenzahl einlesen
                BufferedReader in = new BufferedReader(new FileReader("C:\\Users\\Georg\\Documents\\NetBeansProjects\\0926514_3\\src\\Log.txt"));
                while (in.readLine() != null)
                {
                    z++;
                }
            }
            catch(Exception E)
            {
                System.out.println("Could not open file " + E);
                ok = false;
            }

            //erzeugt ein String-Array für die einzulesenden Werte
            String[] array = new String[z];

            try
            {
            //Zeilenweise einlesen und abspeichern
                BufferedReader in2 = new BufferedReader(new FileReader("C:\\Users\\Georg\\Documents\\NetBeansProjects\\0926514_3\\src\\Log.txt"));
                while ((line = in2.readLine()) != null)
                {
                    array[zaehler] = line;
                    zaehler++;
                }
            }
            catch(Exception E)
            {
                System.out.println("Could not open file " + E );
                ok = false;
            }

            //initialisiert ein Array Runs, welchem alle Zeilen "Run" zur
            //Weiterverarbeitung übergeben werden
            String[] runs = new String[z-2];

            for(int i= 0; i<zaehler; i++)
            {
                //sucht die zeile "Date" aus dem eingelesenen Log-File
                if(array[i].contains("Date"))
                {
                    String[] temporary= array[i].split("\\:");
                    date = temporary[1];
                }
                //sucht die Zeile "Length" aus dem eingelesenen Log-File
                else if(array[i].contains("Length"))
                {
                    String[] temporary= array[i].split("\\:");
                    laenge =  Double.parseDouble(temporary[1]) ;
                }
                //sucht alle Zeilen "Run" aus dem eingelesenen Log-File und
                //speichert diese in das runs-Array um
                else if(array[i].contains("Run"))
                {
                    runs[anzahlLaeufe] = array[i];
                    anzahlLaeufe++;
                }
            }
            
            System.out.println("Datum = " + date);
            System.out.println("Streckenlänge = " + laenge);

            //noch eine kontroll struktur um den korrekten ablauf des Programms
            //zu gewährleisten
            if(date == null || laenge == 0 || anzahlLaeufe == 0)
            {
                System.out.println("Beim einlesen des Log-Files ist ein " +
                                   "Fehler aufgetreten. \n"
                                 + "Vermutlich hat das Log-File ein falsches "
                                 + "Format und/oder falschen Inhalt");
                ok = false;
            }

            //sofern alles richtig funktioniert hat, wird der Code von Bsp 2.5
            //(leicht modifiziert) ausgeführt
            if(ok)
            {
                //Einlesen der Runden-Anzahl als integer
                Scanner sc = new Scanner(System.in);
                ArrayList<Lauf> laeufeList = new ArrayList<Lauf>();
                int verschLaeufer = anzahlLaeufe;

                ////Anzahl der Runden
                //System.out.print("Wieviele Runden wurden gelaufen? ");
                //int anzahlRunden = sc.nextInt();

                //for-Schleife wird anzahlRunden oft durchlaufen,
                for(int i = 0; i < anzahlLaeufe; i++)
                {
                    //der neue (ersetzende) Code
                    String[] temp = runs[i].split("\\:");
                    String name = temp[1];
                    double temporaryTime = Double.parseDouble(temp[2]) ;
                    boolean addRunner = true;

                    System.out.println(laeufeList.size());
                    for(int laufvar=0; laufvar < laeufeList.size(); laufvar++)
                    {
                        if(name.equals(laeufeList.get(laufvar).name))
                        {
                            laeufeList.get(laufvar).AddRunde(temporaryTime);
                            System.out.println("added time at " + laufvar);
                            addRunner = false;
                            verschLaeufer--;
                        }
                    }

                    if(addRunner)
                    {
                        //gibt der ArrayList welche die Läufer speichern soll, einen
                        //Eintrag LAUF, für den eben erstellten Läufer
                        Lauf aktuellerLauf = new Lauf(name, date, laenge);
                        laeufeList.add(aktuellerLauf);
                        aktuellerLauf.AddRunde(temporaryTime);
                        System.out.println("added runner");
                    }
                }

                //Ausgabe:
                System.out.print("Wollen sie jetzt alle Läufer ausgeben?"+
                             " (yes = 1, sorted = 2, no = 0) ");

                int menue = sc.nextInt();
                //einfache Menü-Struktur
                if(menue == 1)
                {
                    //ausgabe unsortiert
                    System.out.println("\n");
                    for(int i = 0; i < laeufeList.size(); i++)
                    {
                        laeufeList.get(i).GetDurchschnittsGeschw();
                        System.out.println("Name: " + (laeufeList.get(i).name) +
                            "\t" + "Durchschnittsgeschwindigkeit: " +
                            laeufeList.get(i).durchschnittsGeschw + " m/sek");
                   }
                }
                else if (menue == 2)
                {
                  //ausgabe sorteirt
                    Collections.sort(laeufeList);
                    System.out.println("\n");
                    for(int i = 0; i < laeufeList.size(); i++)
                    {
                        laeufeList.get(i).GetDurchschnittsGeschw();
                        System.out.println("Name: " + (laeufeList.get(i).name) +
                                "\t" + "Durchschnittsgeschwindigkeit: " +
                                laeufeList.get(i).durchschnittsGeschw + " m/sek");
                    }
                }
            }
        }
        catch (Exception E)
        {
            System.out.println("Unexpected Error: " + E);
        }
    }
}


class Lauf implements Comparable<Lauf>{
    String name;
    String datum;
    double streckenlaenge;
    double durchschnittsGeschw;
    int runden;
    ArrayList<Double> rundenZeitenList = new ArrayList<Double>();


    Lauf(String nameInp, String datumInp, double strecke)
    {
        name = nameInp;
        datum = datumInp;
        streckenlaenge = strecke;
        runden = 0;
    }

    public void AddRundeAufforderung()
    {
        //Fügt eine Weitere Runde der ArrayList der Klasse hinzu
        //(mit zeit-abfrage)
        System.out.print("Rundenzeit in Sekunden: ");
        Scanner sc = new Scanner(System.in);
        int time = sc.nextInt();
        double  dTime = time;
        rundenZeitenList.add(dTime);
        runden++;
    }

    //Eine weitere neue Methode
    public void AddRunde(double rundenzeit)
    {
        rundenZeitenList.add(rundenzeit);
        runden++;
    }

    public int GetAnzahlRunden()
    {
        return rundenZeitenList.size();
    }

    public double GetGesamtstrecke()
    {
        int anzahlRunden = GetAnzahlRunden();
        return (streckenlaenge * anzahlRunden);
    }

    public double GetGesamtZeit()
    {
        double gesamtzeit = 0;
        for(int i = 0; i < GetAnzahlRunden(); i++)
        {
            double zeit = rundenZeitenList.get(i);
            gesamtzeit += zeit;
        }

        return gesamtzeit;
    }

    public void GetDurchschnittsGeschw()
    {
        double gesamtZeit = GetGesamtZeit();
        double strecke = GetGesamtstrecke();

        durchschnittsGeschw = (strecke / gesamtZeit);
    }

    //vergleicht die aktuelle durchschnittsGeschwindigkeit mit der durchschnitts
    //Geschwindigkeiten der Instanzen der Klasse Lauf
    //von Collections.sort(...) benötigt
    public int compareTo( Lauf argument ) {
        if( durchschnittsGeschw < argument.durchschnittsGeschw )
            return 1;
        if( durchschnittsGeschw > argument.durchschnittsGeschw )
            return -1;
        return 0;
    }
}
```

danke schon mal im vorhinein


----------



## SlaterB (10. Dez 2010)

Fehlermeldung? oder falsche Sortierung? dann bitte wenigstens eine Log-Datei zum Testen posten,

oder selber herausfinden:
vor dem Sortieren die Liste mit allen sortier-relevanten Informationen posten, 
notfalls in jedem compareTo die beteiligten Einträge und den Rückgabewert loggen

mit kleinen Listen übersichtlicher zu testen als mit großen


----------



## vienna_devil (10. Dez 2010)

Hier das Log file... das ganze ist einfach als Log.txt abgespeichert


```
Date:12112010
Length:120.13
Run:290:14.1
Run:963:14.5
Run:845:13.9
Run:964:13.8
Run:633:14.2
Run:121:14.5
Run:186:15.0
Run:409:13.5
Run:56:13.7
Run:963:14.2
Run:633:14.1
Run:845:13.8
Run:290:14.4
Run:121:14.5
Run:186:14.8
Run:409:13.7
Run:565:13.8
Run:964:13.7
```


----------



## SlaterB (10. Dez 2010)

...

vor dem Sortieren wurde nie GetDurchschnittsGeschw() aufrufen, ergo wurde überall 0 verglichen,
also dass du das nicht selber gesehen hast.., ist einfach falsch das für dich zu lösen, du musst schon selber schauen was passiert


----------



## vienna_devil (10. Dez 2010)

sry, das hatte ich wirklich nicht bemerkt...
jetzt wo dus sagst isses so offensichtlich... könnte mich dafür ohrfeigen


----------

