Qual é a melhor maneira de verificar se uma String representa um número inteiro em Java?

214

Normalmente, uso o seguinte idioma para verificar se uma String pode ser convertida em um número inteiro.

public boolean isInteger( String input ) {
    try {
        Integer.parseInt( input );
        return true;
    }
    catch( Exception e ) {
        return false;
    }
}

Sou só eu, ou isso parece um pouco idiota? Qual a melhor maneira?


Veja minha resposta (com benchmarks, com base na resposta anterior de CodingWithSpike ) para ver por que eu inverti minha posição e aceitei a resposta de Jonas Klemming para esse problema. Eu acho que esse código original será usado pela maioria das pessoas porque é mais rápido de implementar e mais sustentável, mas é uma ordem de magnitude mais lenta quando dados não inteiros são fornecidos.

Bill the Lizard
fonte
Qual sua idéia sobre o RegExp para a solução?
Akshay Pethani

Respostas:

171

Se você não estiver preocupado com possíveis problemas de estouro, essa função será executada 20 a 30 vezes mais rápido que o 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
fonte
50
(c <= '/' || c> = ':') é um pouco estranho. Eu teria usado (c <'0' || c> '9') ... os operadores <= e> = são mais rápidos em Java?
Anônimo
3
Por que não usar regex? O retorno str.matches ("^ -? \\ d + $") é idêntico ao código acima.
26468 Maglob
15
Eu usaria esse método ou o método original da pergunta antes do regex. Isso é para desempenho, o método original para velocidade de implementação e pura manutenção. A solução regex não tem nada a oferecer.
Bill o Lagarto
4
Estou preocupado com o estouro, mas esse método pode ser adaptado para BigInts e ainda ser muito mais rápido que outros métodos. Caso alguém esteja se perguntando por que estou colocando tanto esforço em um problema tão simples, estou criando uma biblioteca para ajudar na resolução de problemas do Project Euler.
Bill o Lagarto
1
Se você estiver preocupado com a possibilidade de analisar a sequência em um int ou longo, também será necessário verificar se o número inteiro que a sequência representa realmente se encaixa nesses tipos de dados.
Jonas K
65

Você tem, mas você só deve pegar NumberFormatException.

Ovidiu Pacurar
fonte
7
Sim, é considerado péssimo capturar mais exceções do que você precisa.
2626 Chris
Você está certo. A NFE é a única que pode ser descartada, mas ainda é um mau hábito entrar.
Bill the Lizard
Eu acho que um NPE pode ser lançado se a entrada for nula, portanto, seu método provavelmente deve lidar com isso explicitamente, da maneira que você desejar.
Dov Wasserman
@Dov: Você está certo NPE e NFE devem ser explicitamente capturados.
Bill o Lagarto
Essa resposta deve ser a verdadeira resposta para essa pergunta.
Breedly
40

Fez uma referência rápida. Na verdade, as exceções não são tão caras, a menos que você comece a recuperar vários métodos e a JVM tenha que fazer muito trabalho para colocar a pilha de execução no lugar. Ao permanecer no mesmo método, eles não são um bom desempenho.

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

Resultado:

ByException: 31

ByRegex: 453 (nota: recompilando o padrão toda vez)

PorJonas: 16

Concordo que a solução de Jonas K também é a mais robusta. Parece que ele ganha :)

CodingWithSpike
fonte
13
Ótima idéia para comparar todos os três. Para ser justo com os métodos Regex e Jonas, você deve testar com seqüências de caracteres não inteiras, pois é aí que o método Integer.parseInt vai realmente desacelerar.
Bill the Lizard
4
Desculpe, mas este teste de regex não é bom. (1) Você não precisa fazer verificação do motor regex para ^e $segunda vez desde que em matchestoda a cadeia tem de corresponder regex, (2) str.matchescada vez que terá que criar o seu próprio Patternque é caro. Por razões de desempenho, devemos criar esse padrão apenas uma vez fora deste método e usá-lo dentro. (3) Também podemos criar apenas um objeto Matcher e usá-lo reset(CharSequence)para transmitir dados do usuário e retornar seu matches()resultado.
Pshemo 6/11
Então, algo como private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); }deveria ter melhor desempenho.
Pshemo 6/11
@Pshemo Integer.valueOf ("1") e Integer.valueOf ("1") lançam exceção, portanto, a verificação de ^ e $ parece razoável.
Cquezel
1
@cquezel Sim, mas não é necessário, pois matchesestá adicionando ^e $implicitamente. Veja o resultado de " 123".matches("\\d+")e "123".matches("\\d+"). Você verá falsee true. falseserá retornado porque a cadeia começa com espaço, o que impede que ela seja totalmente correspondida pelo regex.
Pshemo
37

Como existe a possibilidade de as pessoas ainda visitarem aqui e sofrerem um viés contra a Regex após os benchmarks ... Então, darei uma versão atualizada do benchmark, com uma versão compilada do Regex. Ao contrário dos benchmarks anteriores, este mostra que a solução Regex realmente apresenta um desempenho consistente bom.

Copiado de Bill the Lizard e atualizado com a versão 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
fonte
1
O tempo ByCompiledRegex precisa incluir a compilação do regex em sua medição de tempo.
Martin Carney
2
@MartinCarney Modifiquei-o e compilei o padrão de referência. Obviamente, minha CPU / JIT é mais rápida, mas se eu a interpolar novamente, o tempo de compilação é 336.
precisa saber é o seguinte
2
para ficar claro, que 336 (ms) é o que acontece quando a compilação do padrão é feita 100k vezes, assim como todas as outras linhas. Com a implicação de que isso é feito apenas uma vez, seu tempo é basicamente zero.
tedder42
Obrigado por definir o registro diretamente nos tempos de regex compilados.
LarsH
Talvez "^[+-]?\\d+$"fosse ainda melhor.
15157 Adam
34
org.apache.commons.lang.StringUtils.isNumeric 

embora a lib padrão do Java realmente perca essas funções utilitárias

Eu acho que o Apache Commons é um "must have" para todo programador Java

Pena que ainda não foi portado para Java5

Łukasz Bownik
fonte
1
O único problema com isto é overflow: SI ainda dar-lhe 1 para mencionar commons-lang :)
javamonkey79
2
O outro problema são os números negativos, mas também tenho +1, pois, na minha opinião, essa abordagem se aproxima mais de uma boa solução.
Sandris
22

Depende parcialmente do que você quer dizer com "pode ​​ser convertido em um número inteiro".

Se você quer dizer "pode ​​ser convertido em int em Java", a resposta do Jonas é um bom começo, mas não termina o trabalho. Passaria 999999999999999999999999999999, por exemplo. Eu adicionaria a chamada try / catch normal da sua própria pergunta no final do método.

As verificações caractere por caractere rejeitam eficientemente casos "nem um número inteiro", deixando "é um número inteiro, mas Java não pode lidar com" casos a serem capturados pela rota de exceção mais lenta. Você também pode fazer isso manualmente, mas seria muito mais complicado.

Jon Skeet
fonte
17

Apenas um comentário sobre o regexp. Todo exemplo fornecido aqui está errado! Se você deseja usar o regexp, não esqueça que a compilação do padrão leva muito tempo. Este:

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

e também isso:

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

causa compilação de padrão em todas as chamadas de método. Para usá-lo corretamente, 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
fonte
5
Você pode obter um pouco mais de desempenho, criando o Matcher também com antecedência e usando o método reset () para aplicá-lo à entrada.
Alan Moore
13

Existe a versão goiaba:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

Ele retornará nulo em vez de lançar uma exceção se falhar ao analisar a sequência.

abalcerek
fonte
3
Melhor resposta IMHO. Use bibliotecas bem testadas em vez de criar sua própria solução. (Veja também a discussão aqui .)
Olivier Cailloux
12

Copiei o código da resposta rally25rs e adicionei alguns testes para dados não inteiros. Os resultados são inegavelmente a favor do método publicado por Jonas Klemming. Os resultados do método Exception que eu publiquei originalmente são muito bons quando você tem dados inteiros, mas são os piores quando não, enquanto os resultados da solução RegEx (que eu aposto que muitas pessoas usam) eram consistentemente ruins. Veja a resposta de Felipe para um exemplo de regex compilado, que é muito mais 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 the Lizard
fonte
6

Isso é mais curto, mas mais curto não é necessariamente melhor (e não captura valores inteiros que estão fora do intervalo, como apontado no comentário da danatel ):

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

Pessoalmente, como a implementação é desviada em um método auxiliar e a exatidão supera o comprimento, eu iria apenas com algo parecido com o que você tem (menos capturar a Exceptionclasse base em vez de NumberFormatException).

Jonny Buchanan
fonte
1
E talvez \\ d {1,10} seja, apesar de não ser perfeito, melhor que \\ d + para capturar números inteiros Java
Maglob 25/08/08
6

Você pode usar o método de correspondências da classe string. O [0-9] representa todos os valores possíveis, + significa que deve ter pelo menos um caractere e * significa que pode ter zero ou mais 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
fonte
1
Nb este fizerem não corresponder "+10" ou "-10"), que normalmente seriam incluídos como inteiros válidos
Tim Wintle
4

E se:

return Pattern.matches("-?\\d+", input);
Kristian
fonte
E o número inteiro 99999999999999999999999999999999?
Danatel 25/10/08
Não se esqueça de verificar o sinal negativo.
Jeremy Ruten 25/10/08
você não precisa ancorar o início e o fim do regex, para não passar "aaa-1999zzz"?
Tim Howland
2
Tim, quando você chama um dos métodos match () (String, Pattern e Matcher, cada um tem um), a regex deve corresponder a toda a entrada, tornando as âncoras redundantes. Para encontrar uma correspondência conforme definido pela maioria dos outros tipos de expressões regulares, use o Matcher # find ().
Alan Moore
4

Esta é uma variação do Java 8 da resposta 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 do teste:

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 do código de teste:

        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
fonte
3

Você acabou de verificar 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
fonte
3

Se sua matriz String contiver inteiros e seqüências de caracteres puros, o código abaixo deve funcionar. Você só precisa olhar para o primeiro personagem. por exemplo, ["4", "44", "abc", "77", "vínculo"]

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

Você também pode usar a classe Scanner e hasNextInt () - e isso permite testar outros tipos também, como carros alegóricos, etc.

Matthew Schinckel
fonte
Essa resposta me deu um lembrete de que eu precisava. Eu esqueci completamente que o Scanner tinha essa função. T-up
Hubro 26/10/10
2

Se você quiser verificar se a string representa um número inteiro que se encaixa em um tipo int, fiz uma pequena modificação na resposta do jonas, para que as strings que representam números inteiros maiores que Integer.MAX_VALUE ou menores que Integer.MIN_VALUE, retornem agora falso. Por exemplo: "3147483647" retornará falso porque 3147483647 é maior que 2147483647 e, da mesma forma, "-2147483649" também retornará falso porque -2147483649 é 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;
}

fonte
1
você pode editar sua resposta e explicar como ela melhora a resposta anterior mencionada?
Gilles Gouaillardet
Obrigado pela ótima resposta. Mas "123", isto é, 123, juntamente com o espaço, é considerado o número inteiro válido.
Saikrishna Radarapu
1
@SaikrishnaRadarapu Eles usam, trim()então essa é claramente uma opção de design intencional.
Guildenstern
2

Você pode tentar utilitários apache

NumberUtils.isCreatable(myText)

Veja o javadoc aqui

Borjab
fonte
1
Parece que este método foi descontinuado no link da versão mais recente ). Aparentemente, você deve usar isCreateable(String).
Guildenstern
Atualizada. Obrigado @Guildenstern
borjab
1

Você provavelmente também precisará levar em consideração o caso de uso:

Se na maioria das vezes você espera que os números sejam válidos, a captura da exceção causa apenas uma sobrecarga de desempenho ao tentar converter números inválidos. Considerando chamando algum isInteger()método e, em seguida, converter usando Integer.parseInt()irá sempre causa uma sobrecarga de desempenho para números válidos - as cordas são analisados duas vezes, uma pelo cheque e uma vez pela conversão.

mobra66
fonte
1

Esta é uma modificação do código de Jonas que verifica se a cadeia está dentro do intervalo para ser convertida em um número inteiro.

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
fonte
1
parece bom, mas o último loop for precisa redefinir para zero (ou 1 se for um número negativo) porque o loop que verifica se cada dígito é um número resultará em eu ser o comprimento da string, portanto, o último loop for nunca vai correr. Eu também usaria as constantes Java Integer.MAX_VALUE e Integer.MIN_VALUE em vez dos números mágicos.
Tim the Enchanter
@ TimtheEnchanter Obrigado pelas sugestões, eu as ignorei completamente. Na minha edição para incorporá-los, usei uma nova variável no primeiro loop for para evitar a declaração if adicional.
Wayne
1

Se você estiver usando a API do Android, poderá usar:

TextUtils.isDigitsOnly(str);
timxyz
fonte
1

Outra opção:

private boolean isNumber(String s) {
    boolean isNumber = true;
    for (char c : s.toCharArray()) {
        isNumber = isNumber && Character.isDigit(c);
    }
    return isNumber;
}
Gabriel Kaffka
fonte
0
is_number = true;
try {
  Integer.parseInt(mystr)
} catch (NumberFormatException  e) {
  is_number = false;
}
Ricardo Acras
fonte
5
Isso está fazendo exatamente a mesma coisa que o pôster está perguntando.
Martin Carney
0

O que você fez funciona, mas você provavelmente nem sempre deve verificar dessa maneira. O lançamento de exceções deve ser reservado para situações "excepcionais" (talvez isso se encaixe no seu caso) e é muito caro em termos de desempenho.

lucas
fonte
Eles só são caros se forem jogados.
Bill o Lagarto
0
Number number;
try {
    number = NumberFormat.getInstance().parse("123");
} catch (ParseException e) {
    //not a number - do recovery.
    e.printStackTrace();
}
//use number
Ran Biron
fonte
0

Isso funcionaria apenas para números inteiros 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
fonte
4
Bem-vindo ao stackoverflow. Antes de ressuscitar um segmento antigo, leia as respostas e comentários anteriores. Este método (e possíveis desvantagens) já foram discutidos.
Leigh
0

Isso funciona para mim. Simplesmente para identificar se uma String é uma primitiva ou um 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
fonte
0

Para verificar todos os caracteres int, você pode simplesmente usar um duplo negativo.

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

[^ 0-9] + $ verifica se existem caracteres que não são inteiros; portanto, o teste falha se for verdadeiro. Apenas NÃO e você obtém sucesso no sucesso.

Roger F. Gay
fonte
Não. Você claramente não testou isso. Isso só retorna true se houver um dígito em algum lugar da string, não se a string for apenas dígitos. O matchesmétodo corresponde à string inteira, não apenas a uma parte dela.
Dawood ibn Kareem
Você não recebe a parte dupla negativa.
23418 Roger F. Gay
Bem, eu não recebo o dobro negativo. Isso simplesmente não funciona. Se você tem uma mistura de dígitos e letras, isso entra no ifbloco. Não deveria.
Dawood ibn Kareem
0

Achar isso útil:

public static boolean isInteger(String self) {
    try {
        Integer.valueOf(self.trim());
        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}
shellbye
fonte
0

Acredito que não há risco zero de correr em uma exceção, porque, como você pode ver abaixo, sempre analisa intcom segurança Stringe não o contrário.

Assim:

  1. Você verifica se cada slot de caractere na sua string corresponde a pelo menos um dos caracteres {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} .

    if(aString.substring(j, j+1).equals(String.valueOf(i)))
  2. Você soma todas as vezes que encontrou nos slots os caracteres acima.

    digits++;
  3. E, finalmente, você verifica se os horários em que você encontrou números inteiros como caracteres são iguais ao comprimento da sequência especificada.

    if(digits == aString.length())

E, na prática, temos:

    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!!");
    }

E os resultados são:

É um número inteiro !!

Não é um número inteiro !!

Da mesma forma, você pode validar se a Stringé a floatou a, doublemas nesses casos você precisa encontrar apenas um. (ponto) na String e, claro, verifique se digits == (aString.length()-1)

Novamente, não há risco zero de executar uma exceção de análise aqui, mas se você planeja analisar uma sequência que sabe que contém um número (digamos, tipo de dados int ), você deve primeiro verificar se ela se encaixa no tipo de dados. Caso contrário, você deve lançá-lo.

Espero ter ajudado

mark_infinite
fonte