Wie würden Sie prüfen, ob ein String eine Zahl ist, bevor Sie ihn parsen?
Beachten Sie, dass dies NPE auslösen würde, wenn das Argument null ist.
Wie würden Sie prüfen, ob ein String eine Zahl ist, bevor Sie ihn parsen?
Die Guava-Bibliothek von Google bietet eine schöne Hilfsmethode für diese Aufgabe: Ints.tryParse
. Sie verwenden es wie Integer.parseInt
aber es gibt zurück null
anstatt eine Exception auszulösen, wenn die Zeichenkette nicht in eine gültige Ganzzahl geparst werden kann. Beachten Sie, dass Integer und nicht int zurückgegeben wird, so dass Sie es wieder in int konvertieren/autoboxen müssen.
Beispiel:
String s1 = "22";
String s2 = "22.2";
Integer oInt1 = Ints.tryParse(s1);
Integer oInt2 = Ints.tryParse(s2);
int i1 = -1;
if (oInt1 != null) {
i1 = oInt1.intValue();
}
int i2 = -1;
if (oInt2 != null) {
i2 = oInt2.intValue();
}
System.out.println(i1); // prints 22
System.out.println(i2); // prints -1
In der aktuellen Version - Guava r11 - ist es jedoch noch als @Beta gekennzeichnet.
Ich habe keinen Benchmark-Test durchgeführt. Wenn man sich den Quellcode anschaut, gibt es einen gewissen Overhead durch eine Menge von Sanitätsprüfungen, aber am Ende verwenden sie Character.digit(string.charAt(idx))
ähnlich, aber etwas anders als die Antwort von @Ibrahim oben. In ihrer Implementierung gibt es keinen Overhead für die Behandlung von Ausnahmen unter der Haube.
Verwenden Sie keine Ausnahmen, um Ihre Werte zu validieren. Verwenden Sie stattdessen Util-Libs wie apache NumberUtils:
NumberUtils.isNumber(myStringValue);
Modifier :
Bitte beachten Sie, dass NumberUtils Ihren Wert als hexadezimal interpretiert, wenn Ihre Zeichenkette mit einer 0 beginnt.
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
Die akzeptierte Antwort, die drei Jahre zuvor gegeben wurde, umfasste bereits Number.isNumber()
.
Das glaube ich nicht. Sie wurde aktualisiert oder op hat die akzeptierte Antwort geändert. Ich erinnere mich, dass die akzeptierte Antwort nicht NumberUtils abdeckte, weshalb ich meine Antwort hinzugefügt habe. Aber danke für den Kommentar
@Goot - Die Geschichte der akzeptierten Antwort zeigt, dass Number.isNumber()
war in der ersten Version der Antwort vom 24. September '12 um 17:01 Uhr vorhanden.
Warum drängen alle auf Ausnahme-/Regex-Lösungen?
Während ich verstehen kann, die meisten Menschen sind in Ordnung mit der Verwendung von Try/Catch, wenn Sie es häufig tun wollen ... es kann extrem anstrengend sein.
Was ich hier getan habe, war die Regex, die parseNumber()-Methoden und die Array-Suchmethode zu nehmen, um zu sehen, welche die effizienteste war. Dieses Mal habe ich nur ganze Zahlen betrachtet.
public static boolean isNumericRegex(String str) {
if (str == null)
return false;
return str.matches("-?\\d+");
}
public static boolean isNumericArray(String str) {
if (str == null)
return false;
char[] data = str.toCharArray();
if (data.length <= 0)
return false;
int index = 0;
if (data[0] == '-' && data.length > 1)
index = 1;
for (; index < data.length; index++) {
if (data[index] < '0' || data[index] > '9') // Character.isDigit() can go here too.
return false;
}
return true;
}
public static boolean isNumericException(String str) {
if (str == null)
return false;
try {
/* int i = */ Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
Die Ergebnisse hinsichtlich der Geschwindigkeit waren:
Done with: for (int i = 0; i < 10000000; i++)...
With only valid numbers ("59815833" and "-59815833"):
Array numeric took 395.808192 ms [39.5808192 ns each]
Regex took 2609.262595 ms [260.9262595 ns each]
Exception numeric took 428.050207 ms [42.8050207 ns each]
// Negative sign
Array numeric took 355.788273 ms [35.5788273 ns each]
Regex took 2746.278466 ms [274.6278466 ns each]
Exception numeric took 518.989902 ms [51.8989902 ns each]
// Single value ("1")
Array numeric took 317.861267 ms [31.7861267 ns each]
Regex took 2505.313201 ms [250.5313201 ns each]
Exception numeric took 239.956955 ms [23.9956955 ns each]
// With Character.isDigit()
Array numeric took 400.734616 ms [40.0734616 ns each]
Regex took 2663.052417 ms [266.3052417 ns each]
Exception numeric took 401.235906 ms [40.1235906 ns each]
With invalid characters ("5981a5833" and "a"):
Array numeric took 343.205793 ms [34.3205793 ns each]
Regex took 2608.739933 ms [260.8739933 ns each]
Exception numeric took 7317.201775 ms [731.7201775 ns each]
// With a single character ("a")
Array numeric took 291.695519 ms [29.1695519 ns each]
Regex took 2287.25378 ms [228.725378 ns each]
Exception numeric took 7095.969481 ms [709.5969481 ns each]
With null:
Array numeric took 214.663834 ms [21.4663834 ns each]
Regex took 201.395992 ms [20.1395992 ns each]
Exception numeric took 233.049327 ms [23.3049327 ns each]
Exception numeric took 6603.669427 ms [660.3669427 ns each] if there is no if/null check
Haftungsausschluss: Ich behaupte nicht, dass diese Methoden zu 100% optimiert sind, sie dienen nur zur Veranschaulichung der Daten
Ausnahmen gibt es nur, wenn die Zahl 4 Zeichen oder weniger hat und jeder String immer eine Zahl... in diesem Fall, warum überhaupt ein Scheck?
Kurz gesagt, es ist äußerst schmerzhaft, wenn man mit try/catch häufig auf ungültige Zahlen stößt, was sinnvoll ist. Eine wichtige Regel, die ich immer befolge, ist NIEMALS try/catch für den Programmablauf verwenden . Dies ist ein Beispiel dafür, warum.
Interessanterweise war das einfache if char <0 || >9 extrem einfach zu schreiben, leicht zu merken (und sollte in mehreren Sprachen funktionieren) und gewinnt fast alle Testszenarien.
Der einzige Nachteil ist, dass ich vermute, dass Integer.parseInt() mit Nicht-ASCII-Zahlen umgehen kann, während die Array-Suchmethode dies nicht tut.
Für diejenigen, die sich fragen, warum ich gesagt habe, dass es einfach ist, sich das Zeichenfeld zu merken, wenn man weiß, dass es keine negativen Zeichen gibt, kann man leicht mit etwas so Verdichtetem davonkommen:
public static boolean isNumericArray(String str) {
if (str == null)
return false;
for (char c : str.toCharArray())
if (c < '0' || c > '9')
return false;
return true;
Abschließend möchte ich noch anmerken, dass ich neugierig auf den Zuweisungsoperator in dem akzeptierten Beispiel war, bei dem alle Stimmen abgegeben wurden. Das Hinzufügen der Zuweisung von
double d = Double.parseDouble(...)
ist nicht nur nutzlos, da man den Wert nicht einmal verwendet, sondern verschwendet auch Verarbeitungszeit und erhöht die Laufzeit um einige Nanosekunden (was zu einem Anstieg von 100-200 ms bei den Tests führte). Ich kann mir nicht vorstellen, warum jemand das tun sollte, da es tatsächlich zusätzliche Arbeit ist, die die Leistung verringert.
Man würde denken, dass würde optimiert werden... obwohl vielleicht sollte ich den Bytecode überprüfen und sehen, was der Compiler tut. Das erklärt nicht, warum es immer zeigte sich als länger für mich aber wenn es irgendwie heraus optimiert ist... daher frage ich mich, was los ist. Als Anmerkung: Mit länger meine ich, den Test für 10000000 Iterationen laufen zu lassen, und das Programm mehrfach (10x+) laufen zu lassen, zeigte immer, dass es langsamer ist.
EDIT: Ein Test für Character.isDigit() wurde aktualisiert.
Wird dadurch nicht jedes Mal ein neuer regulärer Ausdruck kompiliert? Das scheint nicht sehr effizient zu sein.
@SamuelEdwinWard Das ist der ganz Der Grund für diesen Beitrag ist, dass das Regex-Beispiel die Antworten anderer Leute verwendet und zeigt, wie ineffizient es ist. Selbst wenn man versucht, regex im Voraus zu kompilieren und nur das zu verwenden, sind die Zeitunterschiede: 2587 ms für die Regex, die ich von anderen zur Verfügung gestellten Personen gepostet habe, 950 ms, wenn sie im Voraus kompiliert wird, 144 ms, wenn sie als numerisches Array (für 1 Mio. Iterationen der gleichen Zeichenkette) ausgeführt wird. Kompilieren vor der Zeit offensichtlich helfen würde, aber leider ist es immer noch ziemlich schlechter als das Array Weg ... es sei denn, es gibt einige verrückte Optimierung, die ich nicht kenne.
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(.\\d+)?");
}
Der reguläre Ausdruck von CraigTP (siehe oben) erzeugt einige falsch positive Ergebnisse. So wird z. B. "23y4" als Zahl gezählt, da '.' auf jedes Zeichen außer dem Dezimalpunkt passt.
Außerdem wird jede Zahl mit einem führenden '+' abgelehnt.
Eine Alternative, die diese beiden kleineren Probleme vermeidet, ist
public static boolean isNumeric(String str)
{
return str.matches("[+-]?\\d*(\\.\\d+)?");
}
"0."
ist gültig für Double.parseDouble()
und ist ein gültiges Literal gemäß der JLS ( §3.10.2 )!
Wir können versuchen, alle Zahlen in der gegebenen Zeichenkette durch (""), d.h. Leerzeichen, zu ersetzen, und wenn danach die Länge der Zeichenkette Null ist, können wir sagen, dass die gegebene Zeichenkette nur Zahlen enthält. Beispiel:
boolean isNumber(String str){
if(str.length() == 0)
return false; //To check if string is empty
if(str.charAt(0) == '-')
str = str.replaceFirst("-","");// for handling -ve numbers
System.out.println(str);
str = str.replaceFirst("\\.",""); //to check if it contains more than one decimal points
if(str.length() == 0)
return false; // to check if it is empty string after removing -ve sign and decimal point
System.out.println(str);
return str.replaceAll("[0-9]","").length() == 0;
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
42 Stimmen
Alle Lösungen, die mit regulären Ausdrücken vorgeschlagen werden, funktionieren nicht für hexadezimale Zahlen.
0 Stimmen
Und die Übergabe einer Null-Zeichenkette in der Funktion matches(...) führt zur Ausnahme NullPointer.
0 Stimmen
In der Antwort von Max Malysh finden Sie eine prägnante Java 8-Lösung ohne Bibliotheken von Drittanbietern.
0 Stimmen
@HiteshSahu Null-Strings scheinen in der neuesten Version (einschließlich Java 6.x und 7.x) ordnungsgemäß behandelt zu werden.
0 Stimmen
Alle vorgeschlagenen Lösungen zur Verwendung
Integer.parseInt()
nicht in der Lage, Handynummern zu analysieren, dieNumberFormatException
.0 Stimmen
@OscarCastiblanco Alle Zeichenketten sind Zahlen in einer bestimmten Basis.