¿Cuál es la mejor manera de verificar si una cadena representa un número entero en Java?

214

Normalmente uso el siguiente idioma para verificar si una cadena se puede convertir en un 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 duro? ¿Qué es una mejor manera?


Vea mi respuesta (con puntos de referencia, basada en la respuesta anterior de CodingWithSpike ) para ver por qué he revertido mi posición y acepté la respuesta de Jonas Klemming a este problema. Creo que este código original será utilizado por la mayoría de las personas 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.

Bill el lagarto
fuente
¿Cuál es su idea sobre RegExp para la solución?
Akshay Pethani

Respuestas:

171

Si no le preocupan los posibles problemas de desbordamiento, esta función funcionará entre 20 y 30 veces más rápido que el uso 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;
}
Jonas K
fuente
50
(c <= '/' || c> = ':') es un poco extraño. Hubiera utilizado (c <'0' || c> '9') ... ¿son los operadores <= y> = más rápidos en Java?
Anónimo
3
¿Por qué no usar regex? ¿No devuelve str.matches ("^ -? \\ d + $") idéntico al código anterior.
Maglob
15
Usaría este método o el método original de la pregunta antes de la expresión regular. Esto para el rendimiento, el método original para la velocidad de implementación y la simple mantenibilidad. La solución regex no tiene nada que ver.
Bill the Lizard
44
Me preocupa el desbordamiento, pero este método se puede adaptar para BigInts y aún así ser mucho más rápido que otros métodos. En caso de que alguien se pregunte por qué estoy poniendo tanto esfuerzo en un problema tan simple, estoy creando una biblioteca para ayudar a resolver los problemas del Proyecto Euler.
Bill the Lizard
1
Si le preocupa si realmente puede analizar la cadena en un int o largo, también deberá verificar si el entero que representa la cadena realmente se ajusta a esos tipos de datos.
Jonas K
65

Lo tienes, pero solo debes atraparlo NumberFormatException.

Ovidiu Pacurar
fuente
77
Sí, se considera una mala forma capturar más excepciones de las que necesita.
Chris
Tienes razón. NFE es el único que se puede tirar, pero aún es un mal hábito.
Bill the Lizard
Creo que se puede lanzar un NPE si la entrada es nula, por lo que su método probablemente debería manejar eso explícitamente, de la manera que desee.
Dov Wasserman
@Dov: Tienes razón, NPE y NFE deben ser explícitamente capturados.
Bill the Lizard
Esta respuesta debería ser la verdadera respuesta a esta pregunta.
Breedly
40

Hice un punto de referencia rápido. Las excepciones no son realmente tan costosas, a menos que comience a recuperar múltiples métodos y la JVM tenga que hacer mucho trabajo para que la pila de ejecución esté en su lugar. Cuando se quedan en el mismo método, no son malos.

 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;
 }

Salida:

Por excepción: 31

ByRegex: 453 (nota: volver a compilar el patrón cada vez)

Por Jonás: 16

Estoy de acuerdo en que la solución de Jonas K es la más sólida también. Parece que gana :)

CodingWithSpike
fuente
13
Gran idea para comparar los tres. Para ser justos con los métodos Regex y Jonas, debe probar con cadenas no enteras, ya que ahí es donde el método Integer.parseInt realmente se ralentizará.
Bill the Lizard
44
Lo siento, pero esta prueba de expresión regular no es buena. (1) No es necesario hacer la comprobación motor de expresiones regulares para ^y $por segunda vez, ya que en matchestoda la cadena debe coincidir con expresiones regulares, (2) str.matchescada vez que tendrá que crear su propio Pattern, que es caro. Por razones de rendimiento, deberíamos crear dicho patrón solo una vez fuera de este método y usarlo dentro. (3) También podemos crear un solo objeto Matcher y usarlo reset(CharSequence)para pasar datos de usuario y devolver su matches()resultado.
Pshemo
Entonces, algo así private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); }debería tener un mejor rendimiento.
Pshemo
@Pshemo Integer.valueOf ("1") e Integer.valueOf ("1") lanzan una excepción, por lo que verificar ^ y $ parece razonable.
cquezel
1
@cquezel Sí, pero no es obligatorio ya que matchesestá agregando ^e $implícitamente. Echa un vistazo al resultado de " 123".matches("\\d+")y "123".matches("\\d+"). Verás falsey true. falsese devolverá porque la cadena comienza con un espacio que evita que sea regex.
Pshemo
37

Dado que existe la posibilidad de que la gente todavía visite aquí y se predisponga contra Regex después de los puntos de referencia ... Así que voy a dar una versión actualizada del punto de referencia, con una versión compilada de Regex. En oposición a los puntos de referencia anteriores, este muestra que la solución Regex en realidad tiene un rendimiento consistentemente bueno.

Copiado de Bill the Lizard y actualizado con la versión compilada:

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 <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

Resultados:

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
Felipe
fuente
1
El tiempo de ByCompiledRegex debe incluir la compilación de la expresión regular en su medición de tiempo.
Martin Carney
2
@ MartinCarney Lo modifiqué y compilé patrones de compilación. Obviamente mi CPU / JIT es más rápido, pero si lo interpolo de nuevo, el tiempo de compilación es 336.
tedder42
2
Para ser claros, 336 (ms) es lo que sucede cuando la compilación del patrón se realiza 100k veces, al igual que todas las otras líneas. Con la implicación de que solo se hace una vez, su tiempo es básicamente cero.
tedder42
Gracias por establecer el registro directamente en los tiempos de expresiones regulares compiladas.
LarsH
Quizás "^[+-]?\\d+$"sería aún mejor.
Adam
34
org.apache.commons.lang.StringUtils.isNumeric 

aunque la biblioteca estándar de Java realmente pierde esas funciones de utilidad

Creo que Apache Commons es un "must have" para cada programador de Java

lástima que aún no se ha portado a Java5

Łukasz Bownik
fuente
1
El único problema con esto es el desbordamiento: SI todavía te da +1 por mencionar commons-lang :)
javamonkey79
2
El otro problema son los números negativos, pero también hago +1, ya que, en mi opinión, este enfoque se acerca más a una buena solución.
Sandris
22

Depende en parte de lo que quiere decir con "puede convertirse en un entero".

Si quiere decir "puede convertirse en un int en Java", la respuesta de Jonas es un buen comienzo, pero no termina el trabajo. Pasaría 999999999999999999999999999999 por ejemplo. Añadiría la llamada normal try / catch de su propia pregunta al final del método.

Las comprobaciones de carácter por carácter rechazarán eficientemente los casos "no un número entero en absoluto", dejando los casos "es un número entero pero Java no puede manejarlo" para ser detectados por la ruta de excepción más lenta. También podrías hacer esto a mano, pero sería mucho más complicado.

Jon Skeet
fuente
17

Solo un comentario sobre regexp. ¡Cada ejemplo provisto aquí es incorrecto! Si quieres usar regexp, no olvides que compilar el patrón lleva mucho tiempo. Esta:

str.matches("^-?\\d+$")

y también esto:

Pattern.matches("-?\\d+", input);

provoca la compilación del patrón en cada llamada al método. Para usarlo correctamente siga:

import java.util.regex.Pattern;

/**
 * @author Rastislav Komara
 */
public class NaturalNumberChecker {
    public static final Pattern PATTERN = Pattern.compile("^\\d+$");

    boolean isNaturalNumber(CharSequence input) {
        return input != null && PATTERN.matcher(input).matches();
    }
}
Rastislav Komara
fuente
55
Puede exprimir un poco más de rendimiento creando el Matcher con anticipación también y utilizando su método reset () para aplicarlo a la entrada.
Alan Moore
13

Hay versión de guayaba:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

Volverá nulo en lugar de lanzar una excepción si no puede analizar la cadena.

abalcerek
fuente
3
La mejor respuesta en mi humilde opinión. Utilice bibliotecas bien probadas en lugar de desarrollar su propia solución. (También vea la discusión aquí .)
Olivier Cailloux
12

Copié el código de la respuesta rally25rs y agregué algunas pruebas para datos no enteros. Los resultados son indudablemente a favor del método publicado por Jonas Klemming. Los resultados para el método de excepción que publiqué originalmente son bastante buenos cuando tienes datos enteros, pero son los peores cuando no los tienes, mientras que los resultados para la solución RegEx (que apuesto a que mucha gente usa) fueron consistentemente malos. Vea la respuesta de Felipe para un ejemplo de expresiones regulares compiladas, que es mucho más rápido.

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_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+$");
}

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;
}

Resultados:

ByException - integer data: 47
ByException - non-integer data: 547

ByRegex - integer data: 390
ByRegex - non-integer data: 313

ByJonas - integer data: 0
ByJonas - non-integer data: 16
Bill el lagarto
fuente
6

Esto es más corto, pero más corto no es necesariamente mejor (y no capturará valores enteros que estén fuera de rango, como se señala en el comentario de danatel ):

input.matches("^-?\\d+$");

Personalmente, dado que la implementación se elimina en un método auxiliar y la corrección triunfa sobre la longitud, simplemente iría con algo como lo que tienes (menos la captura de la Exceptionclase base en lugar de NumberFormatException).

Jonny Buchanan
fuente
1
Y tal vez \\ d {1,10} es, aunque no perfecto, mejor que \\ d + para atrapar Java
Integers
6

Puede usar el método de coincidencias de la clase de cadena. El [0-9] representa todos los valores que puede ser, el + significa que debe tener al menos un carácter y el * significa que puede tener cero o más caracteres.

boolean isNumeric = yourString.matches("[0-9]+"); // 1 or more characters long, numbers only
boolean isNumeric = yourString.matches("[0-9]*"); // 0 or more characters long, numbers only
Kaitie
fuente
1
Nota: esto no coincide con "+10" o "-10"), que normalmente se incluirían como enteros válidos
Tim Wintle
4

Qué tal si:

return Pattern.matches("-?\\d+", input);
Kristian
fuente
¿Qué pasa con el entero 9999999999999999999999999999999999?
danatel
No olvide verificar el signo negativo.
Jeremy Ruten
¿No necesita anclar el principio y el final de la expresión regular, para que no pase "aaa-1999zzz"?
Tim Howland el
2
Tim, cuando llamas a uno de los métodos de coincidencias () (String, Pattern y Matcher tienen uno), la expresión regular tiene que coincidir con toda la entrada, haciendo que los anclajes sean redundantes. Para encontrar una coincidencia definida por la mayoría de los otros sabores de expresiones regulares, debe usar Matcher # find ().
Alan Moore
4

Esta es una variación de Java 8 de la respuesta de Jonas Klemming:

public static boolean isInteger(String str) {
    return str != null && str.length() > 0 &&
         IntStream.range(0, str.length()).allMatch(i -> i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')
                  || Character.isDigit(str.charAt(i)));
}

Código de prueba:

public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    Arrays.asList("1231231", "-1232312312", "+12313123131", "qwqe123123211", "2", "0000000001111", "", "123-", "++123",
            "123-23", null, "+-123").forEach(s -> {
        System.out.printf("%15s %s%n", s, isInteger(s));
    });
}

Resultados del código de prueba:

        1231231 true
    -1232312312 true
   +12313123131 true
  qwqe123123211 false
              2 true
  0000000001111 true
                false
           123- false
          ++123 false
         123-23 false
           null false
          +-123 false
gil.fernandes
fuente
3

Simplemente marque NumberFormatException : -

 String value="123";
 try  
 {  
    int s=Integer.parseInt(any_int_val);
    // do something when integer values comes 
 }  
 catch(NumberFormatException nfe)  
 {  
          // do something when string values comes 
 }  
duggu
fuente
3

Si su matriz de cadenas contiene enteros y cadenas puros, el siguiente código debería funcionar. Solo tienes que mirar al primer personaje. por ejemplo, ["4", "44", "abc", "77", "enlace"]

if (Character.isDigit(string.charAt(0))) {
    //Do something with int
}
realPK
fuente
3

También puede usar la clase Scanner y usar hasNextInt () , y esto también le permite probar otros tipos, como flotadores, etc.

Matthew Schinckel
fuente
Esta respuesta me dio un recordatorio que necesitaba. Olvidé por completo que Scanner tenía esa función. T-up
Hubro
2

Si desea verificar si la cadena representa un número entero que cabe en un tipo int, hice una pequeña modificación a la respuesta de jonas, para que las cadenas que representan números enteros más grandes que Integer.MAX_VALUE o más pequeños que Integer.MIN_VALUE, ahora regresen falso. Por ejemplo: "3147483647" devolverá falso porque 3147483647 es mayor que 2147483647, y del mismo modo, "-2147483649" también devolverá falso porque -2147483649 es menor que -2147483648.

public static boolean isInt(String s) {
  if(s == null) {
    return false;
  }
  s = s.trim(); //Don't get tricked by whitespaces.
  int len = s.length();
  if(len == 0) {
    return false;
  }
  //The bottom limit of an int is -2147483648 which is 11 chars long.
  //[note that the upper limit (2147483647) is only 10 chars long]
  //Thus any string with more than 11 chars, even if represents a valid integer, 
  //it won't fit in an int.
  if(len > 11) {
    return false;
  }
  char c = s.charAt(0);
  int i = 0;
  //I don't mind the plus sign, so "+13" will return true.
  if(c == '-' || c == '+') {
    //A single "+" or "-" is not a valid integer.
    if(len == 1) {
      return false;
    }
    i = 1;
  }
  //Check if all chars are digits
  for(; i < len; i++) {
    c = s.charAt(i);
    if(c < '0' || c > '9') {
      return false;
    }
  }
  //If we reached this point then we know for sure that the string has at
  //most 11 chars and that they're all digits (the first one might be a '+'
  // or '-' thought).
  //Now we just need to check, for 10 and 11 chars long strings, if the numbers
  //represented by the them don't surpass the limits.
  c = s.charAt(0);
  char l;
  String limit;
  if(len == 10 && c != '-' && c != '+') {
    limit = "2147483647";
    //Now we are going to compare each char of the string with the char in
    //the limit string that has the same index, so if the string is "ABC" and
    //the limit string is "DEF" then we are gonna compare A to D, B to E and so on.
    //c is the current string's char and l is the corresponding limit's char
    //Note that the loop only continues if c == l. Now imagine that our string
    //is "2150000000", 2 == 2 (next), 1 == 1 (next), 5 > 4 as you can see,
    //because 5 > 4 we can guarantee that the string will represent a bigger integer.
    //Similarly, if our string was "2139999999", when we find out that 3 < 4,
    //we can also guarantee that the integer represented will fit in an int.
    for(i = 0; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if(c > l) {
        return false;
      }
      if(c < l) {
        return true;
      }
    }
  }
  c = s.charAt(0);
  if(len == 11) {
    //If the first char is neither '+' nor '-' then 11 digits represent a 
    //bigger integer than 2147483647 (10 digits).
    if(c != '+' && c != '-') {
      return false;
    }
    limit = (c == '-') ? "-2147483648" : "+2147483647";
    //Here we're applying the same logic that we applied in the previous case
    //ignoring the first char.
    for(i = 1; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if(c > l) {
        return false;
      }
      if(c < l) {
        return true;
      }
    }
  }
  //The string passed all tests, so it must represent a number that fits
  //in an int...
  return true;
}

fuente
1
¿puede editar su respuesta y explicar cómo mejora la respuesta anterior que mencionó?
Gilles Gouaillardet
Gracias por la gran respuesta. Pero "123", es decir, 123 junto con el espacio se considera como el entero válido.
Saikrishna Radarapu
1
@SaikrishnaRadarapu Utilizan, por trim()lo que es claramente una elección de diseño intencional.
Guildenstern
2

Puedes probar apache utils

NumberUtils.isCreatable(myText)

Mira el javadoc aquí

borjab
fuente
1
Parece que este método está en desuso en el último enlace de lanzamiento ). Aparentemente deberías usar isCreateable(String)en su lugar.
Guildenstern
Actualizado. Gracias @Guildenstern
borjab
1

Probablemente también deba tener en cuenta el caso de uso:

Si la mayoría de las veces espera que los números sean válidos, la captura de la excepción solo está causando una sobrecarga en el rendimiento al intentar convertir números no válidos. Mientras que llamar a algún isInteger()método y luego convertir usando Integer.parseInt()serán siempre causa una sobrecarga en el rendimiento para los números válidos - las cadenas se analizan dos veces, una vez por el cheque y una vez por la conversión.

mobra66
fuente
1

Esta es una modificación del código de Jonas que comprueba si la cadena está dentro del rango para convertirse en un entero.

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    int i = 0;

    // set the length and value for highest positive int or lowest negative int
    int maxlength = 10;
    String maxnum = String.valueOf(Integer.MAX_VALUE);
    if (str.charAt(0) == '-') { 
        maxlength = 11;
        i = 1;
        maxnum = String.valueOf(Integer.MIN_VALUE);
    }  

    // verify digit length does not exceed int range
    if (length > maxlength) { 
        return false; 
    }

    // verify that all characters are numbers
    if (maxlength == 11 && length == 1) {
        return false;
    }
    for (int num = i; num < length; num++) {
        char c = str.charAt(num);
        if (c < '0' || c > '9') {
            return false;
        }
    }

    // verify that number value is within int range
    if (length == maxlength) {
        for (; i < length; i++) {
            if (str.charAt(i) < maxnum.charAt(i)) {
                return true;
            }
            else if (str.charAt(i) > maxnum.charAt(i)) {
                return false;
            }
        }
    }
    return true;
}
Wayne
fuente
1
se ve bien, pero el último ciclo for debe tener que restablezca a cero (o 1 si es un número negativo) porque el ciclo que verifica si cada dígito es un número dará como resultado que sea la longitud de la cadena, por lo tanto, el último ciclo for nunca correrá También usaría las constantes Java Integer.MAX_VALUE e Integer.MIN_VALUE en lugar de los números mágicos.
Tim el Encantador
@TimtheEnchanter Gracias por las sugerencias, las pasé por alto por completo. En mi edición para incorporarlos, utilicé una nueva variable en el primer bucle for para evitar la declaración extra if.
Wayne
1

Si está utilizando la API de Android, puede usar:

TextUtils.isDigitsOnly(str);
timxyz
fuente
1

Otra opción:

private boolean isNumber(String s) {
    boolean isNumber = true;
    for (char c : s.toCharArray()) {
        isNumber = isNumber && Character.isDigit(c);
    }
    return isNumber;
}
Gabriel Kaffka
fuente
0
is_number = true;
try {
  Integer.parseInt(mystr)
} catch (NumberFormatException  e) {
  is_number = false;
}
Ricardo Acras
fuente
55
Esto está haciendo exactamente lo mismo que el cartel está preguntando.
Martin Carney
0

Lo que hiciste funciona, pero probablemente no siempre deberías comprobarlo de esa manera. Las excepciones de lanzamiento deben reservarse para situaciones "excepcionales" (aunque tal vez eso se ajuste a su caso) y son muy costosas en términos de rendimiento.

lucas
fuente
Solo son costosos si los arrojan.
Bill the Lizard
0
Number number;
try {
    number = NumberFormat.getInstance().parse("123");
} catch (ParseException e) {
    //not a number - do recovery.
    e.printStackTrace();
}
//use number
Ran Biron
fuente
0

Esto funcionaría solo para enteros positivos.

public static boolean isInt(String str) {
    if (str != null && str.length() != 0) {
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) return false;
        }
    }
    return true;        
}
callejero
fuente
44
Bienvenido a stackoverflow. Antes de resucitar un hilo antiguo, asegúrese de leer las respuestas y comentarios anteriores. Este método (y posibles desventajas) ya se discutieron en realidad.
Leigh
0

Esto funciona para mi. Simplemente para identificar si una Cadena es primitiva o un número.

private boolean isPrimitive(String value){
        boolean status=true;
        if(value.length()<1)
            return false;
        for(int i = 0;i<value.length();i++){
            char c=value.charAt(i);
            if(Character.isDigit(c) || c=='.'){

            }else{
                status=false;
                break;
            }
        }
        return status;
    }
Niroshan Abeywickrama
fuente
0

Para verificar todos los caracteres int, simplemente puede usar un doble negativo.

if (! searchString.matches ("[^ 0-9] + $")) ...

[^ 0-9] + $ comprueba si hay caracteres que no son enteros, por lo que la prueba falla si es verdad. Simplemente NO eso y te vuelves verdadero en el éxito.

Roger F. Gay
fuente
No. Claramente no has probado esto. Esto solo devuelve verdadero si hay un dígito en algún lugar de la cadena, no si la cadena es solo dígitos. El matchesmétodo coincide con toda la cadena, no solo una parte de ella.
Dawood ibn Kareem
No obtienes la doble parte negativa.
Roger F. Gay
Bueno, NO obtengo el doble negativo. Esto simplemente no funciona. Si tiene una mezcla de dígitos y letras, esto entra en el ifbloque. No debería
Dawood ibn Kareem
0

Encontrar esto puede ser útil:

public static boolean isInteger(String self) {
    try {
        Integer.valueOf(self.trim());
        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}
adiós
fuente
0

Creo que no hay riesgo de encontrarse con una excepción, porque como puede ver a continuación, siempre analiza intcon seguridad Stringy no al revés.

Entonces:

  1. Usted comprueba si cada ranura de carácter en sus partidos de cuerda, al menos, uno de los personajes { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} .

    if(aString.substring(j, j+1).equals(String.valueOf(i)))
  2. Usted resumir todas las veces que usted encontró en las ranuras de los personajes anteriores.

    digits++;
  3. Y finalmente verifica si las veces que encontró enteros como caracteres es igual a la longitud de la cadena dada.

    if(digits == aString.length())

Y en la práctica tenemos:

    String aString = "1234224245";
    int digits = 0;//count how many digits you encountered
    for(int j=0;j<aString.length();j++){
        for(int i=0;i<=9;i++){
            if(aString.substring(j, j+1).equals(String.valueOf(i)))
                    digits++;
        }
    }
    if(digits == aString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }
    
    String anotherString = "1234f22a4245";
    int anotherDigits = 0;//count how many digits you encountered
    for(int j=0;j<anotherString.length();j++){
        for(int i=0;i<=9;i++){
            if(anotherString.substring(j, j+1).equals(String.valueOf(i)))
                    anotherDigits++;
        }
    }
    if(anotherDigits == anotherString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }

Y los resultados son:

¡Es un número entero!

¡No es un número entero!

Del mismo modo, puede validar si a Stringes a floato a, doublepero en esos casos solo tiene que encontrar uno. (punto) en la Cadena y, por supuesto, compruebe si digits == (aString.length()-1)

Una vez más, no hay riesgo de encontrarse con una excepción de análisis aquí, pero si planea analizar una cadena que se sabe que contiene un número (digamos tipo de datos int ), primero debe verificar si encaja en el tipo de datos. De lo contrario, debe lanzarlo.

Espero haber ayudado

mark_infinite
fuente