Pregunta Cómo comprobar si una cadena es numérica en Java


¿Cómo verificaría si un String fuera un número antes de analizarlo?


701
2017-07-09 09:49


origen


Respuestas:


Con Apache Commons Lang 3.5 y arriba: NumberUtils.isCreatable o StringUtils.isNumeric.

Con Apache Commons Lang 3.4 y abajo: NumberUtils.isNumber o StringUtils.isNumeric.

También puedes usar StringUtils.isNumericSpace que devuelve true para cadenas vacías e ignora espacios internos en la cadena. (Los javadocs enlazados contienen ejemplos detallados para cada método).


559
2017-09-24 17:01



Esto generalmente se realiza con una función simple definida por el usuario (es decir, función Roll-your-own "isNumeric").

Algo como:

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

Sin embargo, si llama mucho a esta función y espera que muchas de las comprobaciones fallen debido a que no se trata de un número, entonces el rendimiento de este mecanismo no será grande, ya que depende de que se emitan excepciones por cada falla, que es una operación bastante costosa.

Un enfoque alternativo puede ser usar una expresión regular para verificar la validez de ser un número:

public static boolean isNumeric(String str)
{
  return str.matches("-?\\d+(\\.\\d+)?");  //match a number with optional '-' and decimal.
}

Tenga cuidado con el mecanismo RegEx anterior, sin embargo, ya que fallará si está usando dígitos no árabes (es decir, números que no sean del 0 al 9). Esto se debe a que la parte "\ d" del RegEx solo coincidirá con [0-9] y efectivamente no tiene conocimiento numérico internacional. (¡Gracias a OregonGhost por señalar esto!)

O incluso otra alternativa es usar el objeto incorporado java.text.NumberFormat de Java para ver si, después de analizar la cadena, la posición del analizador está al final de la cadena. Si es así, podemos suponer que toda la cadena es numérica:

public static boolean isNumeric(String str)
{
  NumberFormat formatter = NumberFormat.getInstance();
  ParsePosition pos = new ParsePosition(0);
  formatter.parse(str, pos);
  return str.length() == pos.getIndex();
}

789
2017-07-09 09:55



si estás en Android, entonces deberías usar:

android.text.TextUtils.isDigitsOnly(CharSequence str)

la documentación se puede encontrar aquí

mantenlo simple. casi todo el mundo puede "reprogramar" (lo mismo).


127
2017-11-22 21:34



Como @CraigTP había mencionado en su excelente respuesta, también tengo problemas de rendimiento similares al usar Excepciones para probar si la cadena es numérica o no. Así que termino dividiendo la cuerda y uso java.lang.Character.isDigit().

public static boolean isNumeric(String str)
{
    for (char c : str.toCharArray())
    {
        if (!Character.isDigit(c)) return false;
    }
    return true;
}

De acuerdo a el Javadoc, Character.isDigit(char) reconocerá correctamente los dígitos no latinos. En lo que respecta al rendimiento, creo que un simple número N de comparaciones donde N es la cantidad de caracteres en la cadena sería más eficiente desde el punto de vista informático que hacer una comparación de expresiones regulares.

ACTUALIZACIÓN: Como señala Jean-François Corbett en el comentario, el código anterior solo validaría enteros positivos, que cubre la mayoría de mi caso de uso. A continuación se muestra el código actualizado que valida correctamente los números decimales de acuerdo con la configuración regional predeterminada utilizada en su sistema, con la suposición de que el separador decimal solo se produce una vez en la cadena.

public static boolean isStringNumeric( String str )
{
    DecimalFormatSymbols currentLocaleSymbols = DecimalFormatSymbols.getInstance();
    char localeMinusSign = currentLocaleSymbols.getMinusSign();

    if ( !Character.isDigit( str.charAt( 0 ) ) && str.charAt( 0 ) != localeMinusSign ) return false;

    boolean isDecimalSeparatorFound = false;
    char localeDecimalSeparator = currentLocaleSymbols.getDecimalSeparator();

    for ( char c : str.substring( 1 ).toCharArray() )
    {
        if ( !Character.isDigit( c ) )
        {
            if ( c == localeDecimalSeparator && !isDecimalSeparatorFound )
            {
                isDecimalSeparatorFound = true;
                continue;
            }
            return false;
        }
    }
    return true;
}

107
2017-08-17 11:30



Java 8 expresiones lambda.

String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );

67
2017-12-13 17:01



La biblioteca de guayaba de Google proporciona un buen método de ayuda para hacer esto: Ints.tryParse. Lo usas como Integer.parseInt pero vuelve null en lugar de arrojar una excepción si la cadena no analiza un entero válido. Tenga en cuenta que devuelve Integer, no int, por lo que debe convertir / autobox de nuevo a int.

Ejemplo:

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

Sin embargo, a partir de la versión actual - Guava r11 - todavía está marcado como @Beta.

No lo he comparado. Al mirar el código fuente, hay una sobrecarga de mucha comprobación de cordura pero al final usan Character.digit(string.charAt(idx)), similar, pero ligeramente diferente de, la respuesta de @Ibrahim anterior. No hay una excepción en el manejo de gastos generales bajo las coberturas en su implementación.


41
2018-01-29 20:13



No use Excepciones para validar sus valores. Use las bibliotecas de Util en lugar de apache NumberUtils:

NumberUtils.isNumber(myStringValue);

Editar:

Tenga en cuenta que, si su cadena comienza con un 0, NumberUtils interpretará su valor como hexadecimal.

NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false

25
2017-08-31 14:14