Frage

ich zu einem Socket-API anschließe, die sehr unflexibel ist. Es wird wieder Zeilen wie:

NAME, CITY, STATE, JOB, MONTH

Aber werden Duplikate haben, weil es keine Aggregation macht. Ich brauche die doppelten Zeilen zu zählen (die in SQL sehr einfach sein würde, aber nicht, soweit ich weiß, in Java).

Beispiel Quelldaten:

NAME,     CITY, STATE, JOB,         MONTH
John Doe, Denver, CO, INSTALLATION, 090301
John Doe, Denver, CO, INSTALLATION, 090301
John Doe, Denver, CO, INSTALLATION, 090301
Jane Doe, Phoenix, AZ, SUPPORT, 090301

Beabsichtigte:

    NAME,    CITY, STATE,          JOB,  MONTH, COUNT
John Doe,  Denver,    CO, INSTALLATION, 090301,   3
Jane Doe, Phoenix,    AZ,      SUPPORT, 090301,   1

Ich kann dies leicht tun für etwa 100.000 Rückkehr Reihen, aber ich mit etwa 60 Millionen in einem Monat zu tun habe. Irgendwelche Ideen?

Edit: Leider sind die Zeilen nicht sortiert zurückgegeben ... noch gibt es eine Option, über die API, sie zu sortieren. Ich erhalte diesen Riesendurcheinander von Sachen, die aggregiert werden muss. Im Moment benutze ich eine Arraylist und tue indexOf (neue Zeile) zu finden, wenn das Element bereits vorhanden ist, aber es wird langsamer desto mehr Zeilen, dass es.

Edit: Zur Klarstellung wäre dies nur noch einmal im Monat ausgeführt wird, am Ende des Monats. Vielen Dank für alle Antworten

War es hilfreich?

Lösung

Sie könnten einen HashSet verwenden, um die vorherige Zeile mit dem gleichen Inhalt zu speichern. (Vorausgesetzt, Ihre Row Objekte haben richtige .hashValue () und .equals () Methoden umgesetzt werden.

So etwas wie dies vielleicht:

Set<Row> previousRows = new HashSet<Row>();
List<Row> rowsInOrder = new LinkedList<Row>();

Dann verwendet wird (unter der Annahme weiter, dass Sie eine incrementCount () -Methode der Zeilenklasse haben):

Row newRow = getNextRow();
if(!previousRows.contains(newRow)){
    previousRows.put(newRow);
    rowsInOrder.add(newRow);
} 
previousRows.get(newRow).incrementCount();

Wenn Sie nicht über die Reihenfolge ist egal, in welcher die Reihen kamen, können Sie die Liste loszuwerden und benutzen Sie einfach die Set.

Andere Tipps

Haben Sie die Flexibilität haben, oder ist dies ein wichtiger genug, um eine Aufgabe in etwas zu investieren, wie Hadoop ? Mit dieser Größe von Daten, möchten Sie in Bezug auf die „map-reducy“ mindset darüber nachzudenken, es zu starten.

Sind Sie in der Lage sofort alle Daten in den Speicher zu passen? Wenn Sie es in einem Arraylist setzen, es klingt wie Sie können.

Wenn das der Fall ist, können Sie einfach eine Implementierung von MultiSet nutzen, wie die in Google Sammlungen

Dann könnten Sie einfach füge alle Zeilen in die multiset wie folgt

Multiset<Row> rowMultiset = HashMultiset.create();
for (Row row: rows) {
  rowMultiset.add(row);
}

Und Sie können durch laufen, mit einer Zählung, mit so etwas wie:

for (Multiset.Entry entry : rowMultiset.entrySet()) {
  System.out.println("row: "+entry.getElement()+", count: "+entry.getCount());
}

Wenn Sie nicht wollen, um eine externe Bibliothek verwenden zu können, etwas Ähnliches unter Verwendung einer HashMap Mapping Reihen auf ganze Zahlen tun.

Wenn es nicht der Fall ist, die alle Ihre Zeilen in dem Speicher passen, ich glaube, der einfachste Ansatz ist nur die Daten in eine Datenbank einzufügen und eine Abfrage zu tun. Datenbanken sind so konzipiert und optimiert für große Datensätze, die nicht passen in den Speicher.

Sind die Reihen immer sortiert zurückgegeben? dh. immer wieder nacheinander die Reihen gruppiert werden? Wenn die Antwort Ja lautet:

1) Initialisieren einen Zähler.

2) Verfolgen der vorherigen Zeile, die Sie gerade an die aktuelle Zeile lesen und vergleichen. Wenn es das gleiche, erhöhen Sie Ihre Zähler. Wenn es anders ist, Ihre Zeile mit dem aktuellen Zählerwert notiert und den Zähler zurücksetzen.

3) Wenn Sie den letzten Datensatz erreichen, stellen Sie sicher, dass die Zeile mit dem aktuellen Zählerstand notieren.

wird diese Strategie ermöglicht es Ihnen, in den großen Datenmengen in einem Stream zu lesen und Ihr Programm Fußabdruck wenig Speicher zu halten, während die kompaktere aggregierte Daten produzieren sind Sie nach.

Ich kann auf vier verschiedene Arten denken, dies zu tun:

  • Wenn Sie über genügend Speicher Darstellungen von 60 Millionen Zeilen im Speicher (weniger Duplikate) zu halten, verwenden Sie ein HashMap<Row, Integer> die Zählungen darstellen.

  • Speichern Sie die Zeilen in einer RDB und dann SQL verwenden zu aggregieren und zählen.

  • die Zeilen in einer großen Datei schreiben und es klassischen Mergesort verwenden, bevor das Zählen  Zeilen in einem Durchgang.

  • so etwas wie Hadoop Verwenden Sie die Zeilen über mehrere Rechner verteilt.

Die Tatsache, dass Sie erwarten, zählt über den Zeitraum von einem Monat zu akkumulieren oder mehr deutet darauf hin, dass Sie berücksichtigen müssen, brauchen die Möglichkeit, dass Ihre Anwendung neu gestartet werden. Das deutet darauf hin, dass ein RDB oder dateibasierte Lösung erforderlich ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top