En Problem der Wortanzahl ist eines der am häufigsten behandelten Probleme in der Big-Data-Welt; es ist sozusagen die "Hello World" von Frameworks wie Hadoop. Sie können im Internet zahlreiche Informationen zu diesem Problem finden.
Ich werde Ihnen trotzdem ein paar Gedanken dazu geben.
Erstens könnten 900000 Wörter immer noch klein genug sein, um eine Hashmap zu erstellen, also schließen Sie den offensichtlichen In-Memory-Ansatz nicht aus. Sie sagten, Pseudocode sei in Ordnung, also:
h = new HashMap<String, Integer>();
for each word w picked up while tokenizing the file {
h[w] = w in h ? h[w]++ : 1
}
Sobald Ihr Datensatz zu groß ist, um eine speicherinterne Hashmap zu erstellen, können Sie die Zählung wie folgt vornehmen:
Tokenize into words writing each word to a single line in a file
Use the Unix sort command to produce the next file
Count as you traverse the sorted file
Diese drei Schritte laufen in einer Unix-Pipeline ab. Lassen Sie das Betriebssystem hier die Arbeit für Sie erledigen.
Jetzt, da Sie noch mehr Daten erhalten, möchten Sie Map-Reduce-Frameworks wie Hadoop einsetzen, um die Wortzählung auf Maschinenclustern durchzuführen.
Ich habe gehört, dass bei obszön großen Datenmengen eine verteilte Umgebung nicht mehr hilfreich ist, weil die Übertragungszeit die Zählzeit übersteigt, und in Ihrem Fall der Wortzählung muss alles "sowieso wieder zusammengesetzt werden", so dass man einige sehr ausgeklügelte Techniken anwenden muss, die Sie vermutlich in Forschungsunterlagen finden.
ADDENDUM
Der OP fragte nach einem Beispiel für die Tokenisierung der Eingabe in Java. Hier ist der einfachste Weg:
import java.util.Scanner;
public class WordGenerator {
/**
* Tokenizes standard input into words, writing each word to standard output,
* on per line. Because it reads from standard input and writes to standard
* output, it can easily be used in a pipeline combined with sort, uniq, and
* any other such application.
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
System.out.println(input.next().toLowerCase());
}
}
}
Hier ist ein Beispiel für die Verwendung dieses Instruments:
echo -e "Hey Moe! Woo\nwoo woo nyuk-nyuk why soitenly. Hey." | java WordGenerator
Diese Ausgaben
hey
moe!
woo
woo
woo
nyuk-nyuk
why
soitenly.
hey.
Sie können diesen Tokenizer mit sort und uniq wie folgt kombinieren:
echo -e "Hey Moe! Woo\nwoo woo nyuk-nyuk why soitenly. Hey." | java WordGenerator | sort | uniq
Ausbeute
hey
hey.
moe!
nyuk-nyuk
soitenly.
why
woo
Wenn Sie nur Buchstaben behalten und alle Interpunktionszeichen, Ziffern und andere Zeichen wegwerfen wollen, ändern Sie Ihre Scanner-Definitionszeile in:
Scanner input = new Scanner(System.in).useDelimiter(Pattern.compile("\\P{L}"));
Und jetzt
echo -e "Hey Moe! Woo\nwoo woo^nyuk-nyuk why#2soitenly. Hey." | java WordGenerator | sort | uniq
Ausbeute
hey
moe
nyuk
soitenly
why
woo
In der Ausgabe gibt es eine Leerzeile; ich überlasse es Ihnen, herauszufinden, wie Sie sie beseitigen können :)