Zählen von Wörtern in einem String mit Java

1. Übersicht

In diesem Tutorial werden verschiedene Methoden zum Zählen von Wörtern in einer bestimmten Zeichenfolge mit Java beschrieben.

2. Verwenden von StringTokenizer

Eine einfache Möglichkeit, Wörter in einer Zeichenfolge in Java zu zählen, ist die Verwendung der StringTokenizer- Klasse:

assertEquals(3, new StringTokenizer("three blind mice").countTokens()); assertEquals(4, new StringTokenizer("see\thow\tthey\trun").countTokens());

Beachten Sie, dass StringTokenizer für uns automatisch Leerzeichen wie Tabulatoren und Zeilenumbrüche übernimmt .

Aber es könnte an einigen Stellen, wie Bindestrichen, schief gehen:

assertEquals(7, new StringTokenizer("the farmer's wife--she was from Albuquerque").countTokens());

In diesem Fall möchten wir, dass „Frau“ und „sie“ unterschiedliche Wörter sind, aber da zwischen ihnen kein Leerzeichen steht, versagen uns die Standardeinstellungen.

Glücklicherweise wird StringTokenizer mit einem anderen Konstruktor geliefert . Wir können ein Trennzeichen an den Konstruktor übergeben, damit das Obige funktioniert:

assertEquals(7, new StringTokenizer("the farmer's wife--she was from Albuquerque", " -").countTokens());

Dies ist praktisch, wenn Sie versuchen, die Wörter in einer Zeichenfolge aus einer CSV-Datei zu zählen:

assertEquals(10, new StringTokenizer("did,you,ever,see,such,a,sight,in,your,life", ",").countTokens());

Also, StringTokenizer ist einfach, und es wird uns die meisten der Weg dorthin.

Mal sehen, welche zusätzlichen Ausdrücke reguläre Ausdrücke uns geben können.

3. Reguläre Ausdrücke

Damit wir für diese Aufgabe einen aussagekräftigen regulären Ausdruck finden, müssen wir definieren, was wir als Wort betrachten: Ein Wort beginnt mit einem Buchstaben und endet entweder mit einem Leerzeichen oder einem Satzzeichen .

In diesem Sinne möchten wir bei einer gegebenen Zeichenfolge diese Zeichenfolge an jedem Punkt teilen, an dem Leerzeichen und Satzzeichen auftreten, und dann die resultierenden Wörter zählen.

assertEquals(7, countWordsUsingRegex("the farmer's wife--she was from Albuquerque"));

Lassen Sie uns die Dinge ein wenig aufdrehen, um die Kraft von Regex zu sehen:

assertEquals(9, countWordsUsingRegex("no&one#should%ever-write-like,this;but:well"));

Es ist nicht praktisch, dieses Problem zu lösen, indem Sie einfach ein Trennzeichen an StringTokenizer übergeben, da wir ein wirklich langes Trennzeichen definieren müssten , um alle möglichen Satzzeichen aufzulisten.

Es stellt sich heraus , dass wir wirklich nicht viel zu tun haben, das Bestehen der regex [\ pP \ s && [^ ']] + auf die Split - Methode der String - Klasse wird es tun :

public static int countWordsUsingRegex(String arg) { if (arg == null) { return 0; } final String[] words = arg.split("[\pP\s&&[^']]+"); return words.length; }

Der reguläre Ausdruck [\ pP \ s && [^ ']] + findet eine beliebige Länge von Satzzeichen oder Leerzeichen und ignoriert das Apostroph-Satzzeichen.

Weitere Informationen zu regulären Ausdrücken finden Sie unter Reguläre Ausdrücke in Baeldung.

4. Schleifen und die String- API

Die andere Methode besteht darin, ein Flag zu haben, das die gefundenen Wörter verfolgt.

Wir setzen das Flag auf WORD, wenn wir auf ein neues Wort stoßen, erhöhen die Wortzahl und kehren dann zu SEPARATOR zurück, wenn wir auf ein Nichtwort stoßen (Satzzeichen oder Leerzeichen).

Dieser Ansatz liefert die gleichen Ergebnisse wie bei regulären Ausdrücken:

assertEquals(9, countWordsManually("no&one#should%ever-write-like,this but well")); 

Wir müssen in besonderen Fällen vorsichtig sein, in denen Satzzeichen keine wirklichen Worttrennzeichen sind , zum Beispiel:

assertEquals(6, countWordsManually("the farmer's wife--she was from Albuquerque"));

Was wir hier wollen, ist, "Bauer" als ein Wort zu zählen, obwohl der Apostroph "" ein Interpunktionszeichen ist.

In der Regex-Version hatten wir die Flexibilität, mithilfe des Regex zu definieren, was nicht als Zeichen qualifiziert ist. Aber jetzt, da wir unsere eigene Implementierung schreiben, müssen wir diesen Ausschluss in einer separaten Methode definieren :

private static boolean isAllowedInWord(char charAt)  

Was wir hier also getan haben, ist, alle Zeichen und gesetzlichen Satzzeichen, in diesem Fall das Apostroph, in einem Wort zuzulassen.

Wir können diese Methode jetzt in unserer Implementierung verwenden:

public static int countWordsManually(String arg) { if (arg == null) { return 0; } int flag = SEPARATOR; int count = 0; int stringLength = arg.length(); int characterCounter = 0; while (characterCounter < stringLength) { if (isAllowedInWord(arg.charAt(characterCounter)) && flag == SEPARATOR) { flag = WORD; count++; } else if (!isAllowedInWord(arg.charAt(characterCounter))) { flag = SEPARATOR; } characterCounter++; } return count; }

Die erste Bedingung markiert ein Wort, wenn es auf eines trifft, und erhöht den Zähler. Die zweite Bedingung prüft, ob das Zeichen kein Buchstabe ist, und setzt das Flag auf SEPARATOR .

5. Schlussfolgerung

In diesem Tutorial haben wir nach Möglichkeiten gesucht, Wörter mithilfe verschiedener Ansätze zu zählen. Wir können je nach Anwendungsfall eine auswählen.

Wie üblich finden Sie den Quellcode für dieses Tutorial auf GitHub.