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.
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;
}
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
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.
9246900cookie-checkWas ist der beste Weg, um zu überprüfen, ob ein String eine Ganzzahl in Java darstellt?yes