Liste mit Lücken mittels Filter aggregieren

PaulGustav

Mitglied
Hallo zusammen.

Ich bin seit einigen Monaten neu in der Java-Welt und stehe vor einem verzwickten Problem, wofür ich gerne einige Ratschläge sammeln würde:

Ich habe eine Liste, welche mittels Zeitstempel (Tag-Monat-Jahr-Stunde-Minute-Sekunde) die Belastungen von Straßen differenziert ausgibt. Diese Listen sehen wie folgt aus:
Listenkopf:
Tag/Zeit, Straße,AnzFahrzeuge,AnzRadfahrer
Listeneinträge:
01-01-2000-12-00-00, Dorfstraße, 10,0
, Schulweg, 5, 1
, Dorstraße, 12, 2
01-01-2000-12-10-00, Dorfstraße, 22, 5
, Schulweg, 10, 3
, Dorfstraße, 27, 3
, Schulweg, 7, 2
usw....

Nun möchte ich erreichen, dass ich mittels Java eine Liste/ ein Set erstelle, welche mir schließlich die Belastungen der einzelnen Straßen zu den einzelnen Zeiten bzw. Tagen zusammenfasst. Quasi in der folgenden Form:
01-01-2000-12-00-00, Dorfstraße, 22,2
01-01-2000-12-00-00, Schulweg, 5, 1
[die Leerzeile dient lediglich der Übersicht]
01-01-2000-12-10-00, Dorfstraße, 49, 8
01-01-2000-12-10-00, Schulweg, 17, 5

Für diese Problematik habe ich mich nun einige Tage mit Listen, Sets und Maps beschäftigt und frage mich nun, ob ich mit meiner Collection einer ArrayList auf dem richtigen Weg bin. Schließlich müss beim Auslesen der "Grunddaten" ja immer die einzelnen Straßenbelastungen festgehalten und infolgedessen aufsummiert werden.

Folglich habe ich dazu den folgende Codes verwendet:
Java:
//Pakete
import java.util.ArrayList;
import java.util.Collection;
import java.io.BufferedReader;

// Klasse für die Grunddaten
public class Files
{
String timeStamp, road;
int vehicles, bikes;
    // hier folgen einige Methoden sowie Konstruktoren
public Files(String timeStamp, String road, int vehicles, int bikes)
{...}
}

//Klasse zum Erstellen der Listen aus einer CSV

public class CreateLists
{
Collection<Files> list = new ArrayList<Files>();
Collection<Files> aggList = new ArrayList<Files>();

BufferedReader br = null;
String line = "";
String cvsSplitBy = ",";
String[] content = line.split(cvsSplitBy);
    // Auslesen der CSV
try{   
while ((line = br.readLine()) != null) {
// Hinzufügen der Listeneinträge in die Liste
// 0=timeStamp, 1=road, 2=vehicles, 3=bikes
list.add(new Files(content[0],content[1],content[2],content[3]));
}
// Es folgen noch Methoden zum Schreiben einer neuen CSV aus der Liste mittels einer For-Schleife
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (br != null)
{
try
{
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}

Ich habe absichtlich einiges ausgelassen um das Skript einigermaßen Minimal zu lassen.
Ich habe nun schon einige Überlegungen angestellt, innerhalb der While-Schleife die Daten so auszulesen, dass
- jeder Zeitstempel, also jede nichtleere Zelle (content[0]), einen Zähler bekommt und dass
- die Straßenbelastungen entsprechend als integer übersetzt und summiert werden.

Gerne würde ich die Lücken der Zeitstempel vorerst entsprechend füllen und dann die Inhalte einer jeden Zeile entsprechend aggregieren. Ist dies so einfach mit der Collection <ArrayList> möglich oder muss ich dabei auf Sets übergehen, um die vielen Filter bzw wenn-dann-Bedinungen zu erfüllen?

Über Anregungen und mögliche Verweise würde ich mich sehr freuen.
 
Du musst das etwas anders aufbauen. Deine Files Klasse (Der Name ist übrigens Mist) muss einen Timestamp haben und eine ArrayList<Street> wobei Street dann wieder ein Klasse ist welche aus Strassenname und Anzahlen der Fahrzeuge und Radfahrer besteht.

Wenn Du dann eine neue Zeile liest und DANACH splittest (in deinem Beispiel splittest du einen leeren String vor der while Schleife) dann suchst du in deiner ArrayList<Files> zunächst nach einem Eintrag mit dem passenden Timestamp. Findest du keinen, erzeugst du eine neue Klasse File und hängst sie an die Liste. Findest du einen, dann schaust du in der ArrayList<Street> ob es schon eine solche Strasse gibt. Wenn ja, dann addierst du die neuen Werte, wenn nein, dann erzeugst du eine neue Strasse und hängst sie an die Liste.

Gruß

Claus
 
Hier einen kleine Anregung , was ich machen würde:

Du durchläufst deine liste und suchst nach einem gleichen Parameter (in deinem Fall sicherlich der Straßenname?). Elemente die deine Bedingung erfüllen kannst du in eine temporäre Liste stecken die du dann auch durchlaufst, deine Elemente zusammen addierst und es dann als neues Element in deine aggList speichern kannst

Gruß
Robert
 
Vielen Dank für die schnellen Rückmeldungen. Habe mich gleich ans Werk gemacht.
Für die Auflistung aller Straßen habe ich nun ein HashSet, was sich alle Namen merkt und diese auch nicht doppelt aufnimmt.

@claus: Kann ich mir das so vorstellen, dass die Files-Klasse nicht wie gehabt die vier Strings (0=timeStamp, 1=road, 2=vehicles, 3=bikes) enthält, sondern nur noch den Timestamp? Dieser bräuchte dann ja auch wieder den Bezug zu der Straße und deren jeweiligen Belastungen. Quasi eine Art TreeMap nur mit mehreren Werten, was nach meiner Recherche so nicht möglich ist.

Der (leere) Split vor der While-Schleife war Murks. Er liegt nun direkt hinter der Schleife.

@Robert: Dein Ansatz hatte ich auch schon irgendwie im Sinn. Da es sich jedoch um einen Datensatz handelt, der ein ganzes Jahr mit allen Tagen und allen möglichen Zeitscheiben beinhaltet, würde ich die Zwischenspeicherung in Listen gerne bevorzugen. Ich denke, dass spart letztendlich Zeit und kann auch anhand der Listen nachvollzogen und ggf geändert werden. Oder denke ich da zu kompliziert?
Vielen Dank trotzdem
 
Paul du solltest dir im klaren werden wonach du deine Daten am Ende Zusammen fassen willst. Willst du alle Daten eines Tages mit den verschiedenen Strassen oder willst du alle Strassen mit den verschiedenen Daten?

Je nachdem musst du halt deine Klassen definieren. Es bringt ja nichts ein Set von Strassen zu machen nur damit keine Strasse doppelt vokommt. Was für eine Redundanz.

Also wenn du später eine Liste mit Daten haben willst in denen jeweils die Strassen mit Anzahlen sind dann sähen Deine Klassen so aus:

Code:
public class StreetUsageDate
{
    LocalDateTime dateTime;
    ArrayList<Street> streetList = new ArrayList<Street>;
}

public class Street
{
    String name;
    int carCount, bicecleCount;
}

Gruß

Claus
 
Ja es soll immer ein Zeitstempel geschrieben werden, der die Straße mit ihren aggregierten Werten wiedergibt.
timestamp --> street(totalVehicles, totalBicycle)
 
Das klingt sehr nach Maps...
Je nachdem wie man's lieber hat Map<LocalDate,StreetUsageData> oder Map<LocalDate,Map<Street,UsageData>, das sollte mit Java 8 recht leicht zusammenzufassen sein...
 
Ich danke euch recht herzlich für die guten Tipps.
Ein Freund meinte ebenso, dass ich die Sache gut mit mehreren Maps lösen könnte. Habe es dann genauso gelöst wie es auch mrBrown empfohlen hat.
 

Zurück
Oben