In diesem Abschnitt wird beschrieben, wie man mithilfe der
Klassen im Java Collection Framework zählt, wie oft ein Wort in einer Datei vorkommt.
Der Konstruktor der Klasse WordCounter bekommt
zwei Streams übergeben:
public WordCounter(Reader reader, PrintWriter writer) {
this.reader = reader;
this.writer = writer;
tokenizer = new StreamTokenizer(reader);
wordTable = new TreeMap();
}
Der übergebene Reader ist mit der Datei verknüpft, aus der ein Text gelesen wird. Auf den übergebenen Writer wird das
Ergebnis des Zählvorgangs ausgegeben. Mithilfe der Klasse StreamTokenizer
wird auf die einzelnen Wörter eines Streams zugegriffen. Im Konstruktor wird
außerdem ein Exemplar der Klasse SortedMap erzeugt, das für den
Zählvorgang benötigt wird.
Der eigentliche Zählvorgang erfolgt durch Aufruf der Methode count():
public void count() throws IOException {
int tokenType;
String token;
Counter counter;
while((tokenType = tokenizer.nextToken())
!= StreamTokenizer.TT_EOF) {
if (tokenType == StreamTokenizer.TT_WORD) {
token = tokenizer.sval;
counter = (Counter)wordTable.get(token);
if (counter == null) {
wordTable.put(token, new Counter(token));
} else {
counter.inc();
}
}
}
}
Aus dem StreamTokenizer werden so lange Tokens angefordert, bis
das Stream-Ende erreicht wird. Der Aufruf von nextToken()
liefert bei einem Aufruf den Typ des nächsten Tokens zurück,
beim Stream-Ende ist das StreamTokenizer.TT_EOF.
Beim Typ StreamTokenizer.TT_WORD kann man
das gelesene Wort im Datenelement sval des StreamTokenizer-Exemplars
auslesen. Danach wird geprüft, ob das Wort bereits als Schlüssel in der TreeMap
vorhanden ist. Falls nicht, wird das Wort in einem Exemplar der Klasse Counter
verpackt und unter dem Schlüssel sval in der TreeMap gespeichert:
wordTable.put(token, new Counter(token));
Counter ist hierbei die Klasse, die den eigentlichen Zählvorgang
übernimmt. Sie merkt sich in einem Datenelement, wie oft ein Wort vorhanden ist:
class Counter {
String word;
int count;
public Counter(String word) {
this.word = word;
count = 1;
}
public void inc() {
count++;
}
public void dump() {
// Zugriff auf Datenelement des
// umschließenden Exemplars
writer.println(word+": "+count);
}
}
Ist
ein Wort bereits als Schlüssel in der TreeMap vorhanden, liefert
die get()-Methode der Klasse TreeMap nämlich das zuvor erzeugte
Counter-Exemplar zum Wort zurück. In diesem Fall wird die Methode
inc() von Counter aufgerufen und somit der interne
Zähler um eins erhöht. Ist das Stream-Ende erreicht, werden die Elemente auf
dem Ausgabe-Stream ausgegeben:
public void print() {
Collection c = wordTable.values();
Iterator it = c.iterator();
while(it.hasNext()) {
Counter counter = (Counter)it.next();
counter.dump();
}
}
Hierbei wird
zunächst über die Methode values() eine
Collection ermittelt. Von diesem Collection-Exemplar
kann man nun wiederum iterator() aufrufen und somit einen
Iterator über die Elemente der Map erhalten. Diese Elemente werden nun der
Reihe nach angefordert und formatiert ausgegeben.
Dadurch, dass eine SortedMap ihre Elemente nach den Schlüsseln sortiert,
werden die Wörter in alphabetischer Reihenfolge vom Iterator zurückgeliefert.