¿Cuál es la mejor manera de comprobar si una cadena representa un número entero en Java?
Normalmente uso el siguiente modismo para comprobar si una cadena se puede convertir en un número entero.
public boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
¿Soy solo yo o esto parece un poco hack? ¿Cuál es una mejor manera?
Vea mi respuesta (con puntos de referencia, basada en la respuesta anterior de CodingWithSpike ) para ver por qué invertí mi posición y acepté la respuesta de Jonas Klemming a este problema. Creo que la mayoría de la gente utilizará este código original porque es más rápido de implementar y más fácil de mantener, pero es mucho más lento cuando se proporcionan datos no enteros.
Si no le preocupan posibles problemas de desbordamiento, esta función funcionará entre 20 y 30 veces más rápido que usar Integer.parseInt()
.
public static boolean isInteger(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 < '0' || c > '9') {
return false;
}
}
return true;
}
Lo tienes, pero sólo debes atraparlo NumberFormatException
.
Hice un punto de referencia rápido. Las excepciones en realidad no son tan costosas, a menos que comiences a recuperar múltiples métodos y la JVM tenga que trabajar mucho para poner la pila de ejecución en su lugar. Cuando se mantienen en el mismo método, no tienen malos resultados.
public void RunTests()
{
String str = "1234567890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(str);
long endTime = System.currentTimeMillis();
System.out.print("ByException: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(str);
endTime = System.currentTimeMillis();
System.out.print("ByRegex: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(str);
endTime = System.currentTimeMillis();
System.out.print("ByJonas: ");
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+$");
}
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 <= '/' || c >= ':') {
return false;
}
}
return true;
}
Producción:
Por excepción: 31
ByRegex: 453 (nota: volver a compilar el patrón cada vez)
Por Jonas: 16
Estoy de acuerdo en que la solución de Jonas K también es la más sólida. Parece que gana :)