Was ist der beste Weg, um zu überprüfen, ob ein String eine Ganzzahl in Java darstellt?

Lesezeit: 6 Minuten

Was ist der beste Weg um zu uberprufen ob ein
Bill die Eidechse

Normalerweise verwende ich das folgende Idiom, um zu prüfen, ob ein String in eine Ganzzahl konvertiert werden kann.

public boolean isInteger( String input ) {
    try {
        Integer.parseInt( input );
        return true;
    }
    catch( Exception e ) {
        return false;
    }
}

Ist es nur ich, oder scheint das ein bisschen hackish zu sein? Was ist ein besserer Weg?


Sehen Sie sich meine Antwort (mit Benchmarks, basierend auf der früheren Antwort von CodingWithSpike) an, um zu sehen, warum ich meine Position umgekehrt und die Antwort von Jonas Klemming auf dieses Problem akzeptiert habe. Ich denke, dass dieser ursprüngliche Code von den meisten Leuten verwendet wird, weil er schneller zu implementieren und wartungsfreundlicher ist, aber er ist um Größenordnungen langsamer, wenn nicht ganzzahlige Daten bereitgestellt werden.

1646320632 131 Was ist der beste Weg um zu uberprufen ob ein
Ovidiu Pacurar

Sie haben es, aber Sie sollten nur fangen NumberFormatException.

  • Ja, es gilt als schlechter Stil, mehr Ausnahmen abzufangen, als Sie brauchen.

    – Chris

    26. Oktober 2008 um 1:28 Uhr

  • Du hast recht. NFE ist die einzige, die geworfen werden kann, aber es ist immer noch eine schlechte Angewohnheit, sich darauf einzulassen.

    – Bill die Eidechse

    26. Oktober 2008 um 3:26 Uhr

  • Ich denke, ein NPE kann ausgelöst werden, wenn die Eingabe null ist, also sollte Ihre Methode dies wahrscheinlich explizit behandeln, wie auch immer Sie möchten.

    – Dov Wassermann

    26. Oktober 2008 um 8:07 Uhr

  • @Dov: Sie haben Recht, NPE und NFE sollten beide explizit gefangen werden.

    – Bill die Eidechse

    26. Oktober 2008 um 12:35 Uhr

  • Meiner Meinung nach ist diese Folge von Kommentaren tatsächlich ein gutes Argument zum fangen java.lang.Exception (oder Throwable), demonstriert, wie es einfach zu leicht ist, einen zu übersehen.

    – Reto Höhener

    26. Juli 2013 um 6:35 Uhr

  • Tolle Idee, alle drei zu benchmarken. Um den Regex- und Jonas-Methoden gegenüber fair zu sein, sollten Sie mit Strings testen, die keine Ganzzahlen sind, da die Integer.parseInt-Methode hier wirklich langsamer wird.

    – Bill die Eidechse

    26. Oktober 2008 um 13:00 Uhr

  • Tut mir leid, aber dieser Regex-Test ist nicht gut. (1) Sie müssen keine Regex-Engine-Prüfung durchführen ^ und $ zweites Mal seit in matches gesamter String muss mit Regex übereinstimmen, (2) str.matches Jedes Mal muss es sein eigenes erstellen Pattern was teuer ist. Aus Performance-Gründen sollten wir ein solches Pattern nur einmal außerhalb dieser Methode erstellen und innerhalb verwenden. (3) Wir können auch nur ein Matcher-Objekt erstellen und dieses verwenden reset(CharSequence) Benutzerdaten zu übergeben und zurückzugeben matches() Ergebnis.

    – Pschemo

    6. November 2013 um 15:01 Uhr

  • Also sowas wie private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); } sollte eine bessere Leistung haben.

    – Pschemo

    6. November 2013 um 15:02 Uhr

  • @Pshemo Integer.valueOf(” 1″) und Integer.valueOf(“1 “) lösen beide eine Ausnahme aus, sodass die Überprüfung auf ^ und $ sinnvoll erscheint.

    – cquezel

    12. Mai 2015 um 17:33 Uhr

  • @cquezel Ja, ist es aber nicht erforderlich seit matches fügt hinzu ^ und $ implizit. Sehen Sie sich das Ergebnis von an " 123".matches("\\d+") und "123".matches("\\d+"). Du wirst sehen false und true. false wird zurückgegeben, da die Zeichenfolge mit einem Leerzeichen beginnt, was verhindert, dass sie vollständig von Regex abgeglichen wird.

    – Pschemo

    12. Mai 2015 um 18:07 Uhr

org.apache.commons.lang.StringUtils.isNumeric 

obwohl die Standardbibliothek von Java solche Hilfsfunktionen wirklich vermisst

Ich denke, dass Apache Commons ein “must have” für jeden Java-Programmierer ist

Schade, dass es noch nicht auf Java5 portiert wurde

  • Das einzige Problem dabei ist der Überlauf: SI gibt Ihnen immer noch +1 für die Erwähnung von commons-lang 🙂

    – javamonkey79

    27. Juli 2010 um 23:55 Uhr

  • Das andere Problem sind negative Zahlen, aber ich habe auch +1, da dieser Ansatz meiner Meinung nach einer guten Lösung am nächsten kommt.

    – Sandris

    9. Januar 2013 um 7:38 Uhr

Da die Möglichkeit besteht, dass die Leute hier immer noch vorbeischauen und nach den Benchmarks gegen Regex voreingenommen sind … Also werde ich eine aktualisierte Version des Benchmarks mit einer kompilierten Version der Regex geben. Im Gegensatz zu den vorherigen Benchmarks zeigt dieser, dass die Regex-Lösung tatsächlich eine konstant gute Leistung aufweist.

Von Bill the Lizard kopiert und mit der kompilierten Version aktualisiert:

private final Pattern pattern = Pattern.compile("^-?\\d+$");

public void runTests() {
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByCompiledRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByCompiledRegex - non-integer data: ");
    System.out.println(endTime - startTime);


    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

private boolean IsInt_ByCompiledRegex(String str) {
    return pattern.matcher(str).find();
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= "https://stackoverflow.com/" || c >= ':') {
                    return false;
            }
    }
    return true;
}

Ergebnisse:

ByException - integer data: 45
ByException - non-integer data: 465

ByRegex - integer data: 272
ByRegex - non-integer data: 131

ByCompiledRegex - integer data: 45
ByCompiledRegex - non-integer data: 26

ByJonas - integer data: 8
ByJonas - non-integer data: 2

  • Das einzige Problem dabei ist der Überlauf: SI gibt Ihnen immer noch +1 für die Erwähnung von commons-lang 🙂

    – javamonkey79

    27. Juli 2010 um 23:55 Uhr

  • Das andere Problem sind negative Zahlen, aber ich habe auch +1, da dieser Ansatz meiner Meinung nach einer guten Lösung am nächsten kommt.

    – Sandris

    9. Januar 2013 um 7:38 Uhr

Was ist der beste Weg um zu uberprufen ob ein
Jon Skeet

Es hängt teilweise davon ab, was Sie mit “kann in eine Ganzzahl konvertiert werden” meinen.

Wenn Sie “kann in Java in ein int konvertiert werden” meinen, dann ist die Antwort von Jonas ein guter Anfang, beendet aber die Arbeit nicht ganz. Es würde zum Beispiel 999999999999999999999999999999 passieren. Ich würde den normalen Try/Catch-Aufruf aus Ihrer eigenen Frage am Ende der Methode hinzufügen.

Die zeichenweisen Prüfungen weisen „überhaupt keine Ganzzahl“-Fälle effizient zurück, sodass „es ist eine Ganzzahl, aber Java kann damit nicht umgehen“-Fälle von der langsameren Ausnahmeroute abgefangen werden. Sie könnten tun dies auch ein bisschen von Hand, aber es wäre ein viel komplizierter.

924690cookie-checkWas ist der beste Weg, um zu überprüfen, ob ein String eine Ganzzahl in Java darstellt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy