Prüfen Sie, ob ein String in Java numerisch ist

Überprüfen Sie, ob eine Zeichenfolge in Java numerisch ist

1. Einführung

Während des Betriebs mitStrings, we muss häufig herausgefunden werden, obString eine gültige Zahl ist oder nicht.

In this tutorial, we’ll explore multiple ways to detect if the given String is numeric, zuerst mit einfachem Java, dann mit regulären Ausdrücken und schließlich mit externen Bibliotheken.

Sobald wir verschiedene Implementierungen besprochen haben, verwenden wir Benchmarks, um eine Vorstellung davon zu bekommen, welche Methoden optimal sind.

Beginnen wir mit einigen Voraussetzungen, bevor wir zum Hauptinhalt übergehen.

2. Voraussetzung

Im letzten Teil dieses Artikels verwenden wir die externe Bibliothek von Apache Commons. Fügen Sie die folgenden Zeilen inpom.xml hinzu, um diese Abhängigkeit einzuschließen:


    org.apache.commons
    commons-lang3
    3.7

Die neueste Version dieser Bibliothek finden Sie unterMaven Central.

3. Verwenden von Plain Java

Der einfachste und zuverlässigste Weg, um zu überprüfen, ob einString is numerisch ist oder nicht, besteht darin, es mit den in Java integrierten Methoden zu analysieren:

  1. Integer.parseInt(String)

  2. Float.parseFloat(String)

  3. Double.parseDouble(String)

  4. Long.parseLong(String)

  5. neue BigInteger (String)

Wenn diese Methoden keineNumberFormatException auslösen, bedeutet dies, dass die Analyse erfolgreich war und dieString is numerisch ist:

public static boolean isNumeric(String strNum) {
    try {
        double d = Double.parseDouble(strNum);
    } catch (NumberFormatException | NullPointerException nfe) {
        return false;
    }
    return true;
}

Lassen Sie uns diese Methode in Aktion sehen:

assertThat(isNumeric("22")).isTrue();
assertThat(isNumeric("5.05")).isTrue();
assertThat(isNumeric("-200")).isTrue();
assertThat(isNumeric("10.0d")).isTrue();
assertThat(isNumeric("   22   ")).isTrue();

assertThat(isNumeric(null)).isFalse();
assertThat(isNumeric("")).isFalse();
assertThat(isNumeric("abc")).isFalse();

In unsererisNumeric() -Smethod suchen wir nur nach Werten vom TypDouble. Diese Methode kann jedoch auch geändert werden, um nachInteger,Float,Long zu suchen ) Schleifen Sie große Zahlen mit einer der zuvor verwendeten Analysemethoden.

Diese Methoden werden auch imJava String Conversions -Sartikel diskutiert.

3.1. Überprüfen der Eingänge mitScanner

java.utilScanner Klasse ist vielleicht der einfachste Weg in einfachem Java, primitive Arten von Eingaben wieint,double usw. zu erhalten. Es werden auch verschiedene APIs bereitgestellt, um zu überprüfen, ob die angegebene Eingabe von einem bestimmten Typ ist oder nicht.

Zum Beispielthe following APIs check whether the input is of type integer, long or float:

  • scanner.hasNextInt()

  • scanner.hasNextLong()

  • scanner.hasNextFloat()

Diese APIs geben einfachetrue oderfalse basierend auf den Eingabetypen zurück. Mit diesen APIs können wir sicherstellen, dass die nächste Eingabe vom gewünschten Typ ist.

Das folgende Snippet prüft, ob die Eingabe eine Ganzzahl ist oder nicht:

try (Scanner scanner = new Scanner(System.in)) {
    System.out.println("Enter an integer : ");
    if (scanner.hasNextInt()) {
        System.out.println("You entered : " + scanner.nextInt());
    } else {
        System.out.println("The input is not an integer");
    }
}

Ebenso können wir andere APIs verwenden, um andere Typen zu überprüfen.

4. Reguläre Ausdrücke verwenden

Verwenden wir nun den regulären Ausdruck-?\d+(\.\d+)?, um mit dem numerischenStrings übereinzustimmen, der aus der positiven oder negativen Ganzzahl und den Gleitkommazahlen besteht.

Es versteht sich jedoch von selbst, dass wir diesen regulären Ausdruck definitiv modifizieren können, um eine Vielzahl von Regeln zu identifizieren und zu verarbeiten. Hier halten wir es einfach.

Lassen Sie uns diesen regulären Ausdruck aufteilen und sehen, wie es funktioniert:

  • -? - Dieser Teil gibt an, ob die angegebene Zahl negativ ist. Der Bindestrich „“ sucht buchstäblich nach dem Bindestrich und das Fragezeichen „?“ markiert seine Anwesenheit als optional

  • \d+ - sucht nach einer oder mehreren Ziffern

  • (\.\d+)? - Dieser Teil von Regex dient zur Identifizierung von Float-Nummern. Hier suchen wir nach einer oder mehreren Ziffern, gefolgt von einem Punkt. Das Fragezeichen am Ende zeigt an, dass diese vollständige Gruppe optional ist

Die regulären Ausdrücke sind ein sehr breites Thema. Um einen kurzen Überblick zu erhalten, besuchen Siethis linked example article.

Lassen Sie uns zunächst eine Methode mit dem obigen regulären Ausdruck erstellen:

public static boolean isNumeric(String strNum) {
    return strNum.matches("-?\\d+(\\.\\d+)?");
}

Schauen wir uns nun einige Aussagen für die obige Methode an:

assertThat(isNumeric("22")).isTrue();
assertThat(isNumeric("5.05")).isTrue();
assertThat(isNumeric("-200")).isTrue();

assertThat(isNumeric("abc")).isFalse();

 5. Verwenden von Apache Commons

In diesem Abschnitt werden verschiedene Methoden erläutert, die in der Apache Commons-Bibliothek verfügbar sind.

5.1. NumberUtils.isCreatable(String)

NumberUtils von Apache Commons bietet eine statische MethodeNumberUtils.isCreatable(String) , mit der überprüft wird, ob die Java-Nummer eines gültig ist oder nicht.

Diese Methode akzeptiert:

  1. Hexadezimalzahlen, die mit 0x oder 0X beginnen

  2. Oktalzahlen, die mit einer führenden 0 beginnen

  3. Wissenschaftliche Notation (zum Beispiel 1.05e-10)

  4. Mit einem Typenkennzeichen gekennzeichnete Nummern (z. B. 1L oder 2.2d)

Wenn die angegebene Zeichenfolgenull oderempty/blank ist, wird sie nicht als Zahl betrachtet, und diese Methode gibt in diesem Fallfalse in zurück.

Lassen Sie uns einige Tests mit dieser Methode ausführen:

assertThat(NumberUtils.isCreatable("22")).isTrue();
assertThat(NumberUtils.isCreatable("5.05")).isTrue();
assertThat(NumberUtils.isCreatable("-200")).isTrue();
assertThat(NumberUtils.isCreatable("10.0d")).isTrue();
assertThat(NumberUtils.isCreatable("1000L")).isTrue();
assertThat(NumberUtils.isCreatable("0xFF")).isTrue();
assertThat(NumberUtils.isCreatable("07")).isTrue();
assertThat(NumberUtils.isCreatable("2.99e+8")).isTrue();

assertThat(NumberUtils.isCreatable(null)).isFalse();
assertThat(NumberUtils.isCreatable("")).isFalse();
assertThat(NumberUtils.isCreatable("abc")).isFalse();
assertThat(NumberUtils.isCreatable(" 22 ")).isFalse();
assertThat(NumberUtils.isCreatable("09")).isFalse();

Beachten Sie, wie wir in den Zeilen 6, 7 und 8true -Sassertionen für Hexadezimalzahlen, Oktalzahlen und wissenschaftliche Notationen erhalten.

Auch in Zeile 14 gibt der String“09” false zurück, da das vorhergehende“0” angibt, dass dies eine Oktalzahl ist und“09” keine gültige Oktalzahl ist.

Für jede Eingabe, dietrue mit dieser Methode zurückgibt, können wirNumberUtils.createNumber(String) verwenden, die uns die gültige Zahl gibt.

5.2. NumberUtils.isParsable(String)

Die MethodeNumberUtils.isParsable(String) prüft, ob die angegebeneString -parsable ist oder nicht.

Analysierbare Zahlen sind solche, die mit einer der Analysemethoden wieInteger.parseInt(String),Long.parseLong(String),Float.parseFloat(String) oderDouble.parseDouble(String) erfolgreich analysiert werden.

Im Gegensatz zuNumberUtils.isCreatable() akzeptiert diese Methode keine Hexadezimalzahlen, wissenschaftlichen Notationen oder Zeichenfolgen, die mit einem Typqualifikator enden, d. H. ‘f', ‘F', ‘d' ,'D' ,'l'or_ 'L' ._

Schauen wir uns einige Affirmationen an:

assertThat(NumberUtils.isParsable("22")).isTrue();
assertThat(NumberUtils.isParsable("-23")).isTrue();
assertThat(NumberUtils.isParsable("2.2")).isTrue();
assertThat(NumberUtils.isParsable("09")).isTrue();

assertThat(NumberUtils.isParsable(null)).isFalse();
assertThat(NumberUtils.isParsable("")).isFalse();
assertThat(NumberUtils.isParsable("6.2f")).isFalse();
assertThat(NumberUtils.isParsable("9.8d")).isFalse();
assertThat(NumberUtils.isParsable("22L")).isFalse();
assertThat(NumberUtils.isParsable("0xFF")).isFalse();
assertThat(NumberUtils.isParsable("2.99e+8")).isFalse();

In Zeile 4 wird im Gegensatz zuNumberUtils.isCreatable() die mit der Zeichenfolge“0” beginnende Zahl nicht als Oktalzahl, sondern als normale Dezimalzahl betrachtet und gibt daher true zurück.

Wir können diese Methode als Ersatz für das verwenden, was wir in Abschnitt 3 getan haben, in dem wir versuchen, eine Zahl zu analysieren und nach Fehlern zu suchen.

5.3. StringUtils.isNumeric(CharSequence)

Die MethodeStringUtils.isNumeric(CharSequence) prüft ausschließlich Unicode-Ziffern. Das heisst:

  1. Alle Ziffern aus einer beliebigen Sprache, die eine Unicode-Ziffer ist, sind zulässig

  2. Da ein Dezimalpunkt nicht als Unicode-Ziffer betrachtet wird, ist er nicht gültig

  3. Vorzeichen (entweder positiv oder negativ) sind ebenfalls nicht akzeptabel

Lassen Sie uns nun diese Methode in Aktion sehen:

assertThat(StringUtils.isNumeric("123")).isTrue();
assertThat(StringUtils.isNumeric("١٢٣")).isTrue();
assertThat(StringUtils.isNumeric("१२३")).isTrue();

assertThat(StringUtils.isNumeric(null)).isFalse();
assertThat(StringUtils.isNumeric("")).isFalse();
assertThat(StringUtils.isNumeric("  ")).isFalse();
assertThat(StringUtils.isNumeric("12 3")).isFalse();
assertThat(StringUtils.isNumeric("ab2c")).isFalse();
assertThat(StringUtils.isNumeric("12.3")).isFalse();
assertThat(StringUtils.isNumeric("-123")).isFalse();

Beachten Sie, dass die Eingabeparameter in den Zeilen 2 und 3 die Zahlen123 in Arabic bzw. Devanagari darstellen. Da es sich um gültige Unicode-Ziffern handelt, gibt diese Methodetrue für sie zurück.

5.4. StringUtils.isNumericSpace(CharSequence)

DieStringUtils.isNumericSpace(CharSequence) werden ausschließlich für Unicode-Ziffern und / oder Leerzeichen überprüft. Dies ist dasselbe wieStringUtils.isNumeric() mit dem einzigen Unterschied, dass es auch Leerzeichen akzeptiert, nicht nur führende und nachfolgende Leerzeichen, sondern auch, wenn sie zwischen Zahlen liegen:

assertThat(StringUtils.isNumericSpace("123")).isTrue();
assertThat(StringUtils.isNumericSpace("١٢٣")).isTrue();
assertThat(StringUtils.isNumericSpace("")).isTrue();
assertThat(StringUtils.isNumericSpace("  ")).isTrue();
assertThat(StringUtils.isNumericSpace("12 3")).isTrue();

assertThat(StringUtils.isNumericSpace(null)).isFalse();
assertThat(StringUtils.isNumericSpace("ab2c")).isFalse();
assertThat(StringUtils.isNumericSpace("12.3")).isFalse();
assertThat(StringUtils.isNumericSpace("-123")).isFalse();

6. Benchmarks

Bevor wir diesen Artikel abschließen, gehen wir kurz die Benchmark-Ergebnisse durch, anhand derer wir analysieren können, welche der oben genannten Methoden optimale Ansätze sind:

Benchmark                                     Mode   Cnt    Score     Error  Units
Benchmarking.usingCoreJava                    avgt   20   152.061 ±  24.300  ns/op
Benchmarking.usingRegularExpressions          avgt   20  1299.258 ± 175.688  ns/op
Benchmarking.usingNumberUtils_isCreatable     avgt   20    63.811 ±   5.638  ns/op
Benchmarking.usingNumberUtils_isParsable      avgt   20    58.706 ±   5.299  ns/op
Benchmarking.usingStringUtils_isNumeric       avgt   20    35.599 ±   8.498  ns/op
Benchmarking.usingStringUtils_isNumericSpace  avgt   20    37.010 ±   4.394  ns/op

Wie wir sehen können, sind reguläre Ausdrücke die teuerste Operation, gefolgt von einer Java-basierten Kernlösung. Alle anderen Operationen, die die Apache Commons-Bibliothek verwenden, sind im Großen und Ganzen gleich.

7. Fazit

In diesem Artikel haben wir verschiedene Möglichkeiten untersucht, ob einString is numerisch ist oder nicht. Wir haben uns beide Lösungen angesehen - eingebaute Methoden und auch externe Bibliotheken.

Wie immer kann die Implementierung aller oben angegebenen Beispiele und Codefragmente einschließlich des zur Durchführung von Benchmarks verwendeten Codesover on GitHub gefunden werden.