Verifique se uma string é numérica em Java
1. Introdução
Muitas vezes, durante a operação em Strings, precisamos descobrir se um String é um número válido ou não.
*Neste tutorial, exploraremos várias maneiras de detectar se o __String __ fornecido é numérico* , primeiro usando Java simples, depois expressões regulares e finalmente usando bibliotecas externas.
Quando terminarmos de discutir várias implementações, usaremos benchmarks para ter uma idéia de quais métodos são ideais.
Vamos começar com alguns pré-requisitos antes de seguirmos para o conteúdo principal.
*2. Pré-requisito *
Na parte final deste artigo, usaremos a biblioteca externa do Apache Commons. Para incluir essa dependência, adicione as seguintes linhas em pom.xml:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
A versão mais recente desta biblioteca pode ser encontrada em https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.apache.commons%22%20AND%20a%3A%22commons-lang3 % 22 [Maven Central].
===* 3. Usando Java Simples *
Talvez a maneira mais fácil e confiável de verificar se um String é numérico ou não, analisando-o usando os métodos internos do Java:
-
_Integer.parseInt (String) _
-
_Float.parseFloat (String) _
-
_Double.parseDouble (String) _
-
_Long.parseLong (String) _
-
_novo BigInteger (String) _
Se esses métodos não lançarem _https://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html [NumberFormatException] _, significa que a análise foi bem-sucedida e a String is numérico:
public static boolean isNumeric(String strNum) {
try {
double d = Double.parseDouble(strNum);
} catch (NumberFormatException | NullPointerException nfe) {
return false;
}
return true;
}
Vamos ver este método em ação:
assertThat(isNumeric("22")).isTrue();
assertThat(isNumeric("5.05")).isTrue();
assertThat(isNumeric("-200")).isTrue();
assertThat(isNumeric("10.0d")).isTrue();
assertThat(isNumeric(" 22 ")).isTrue();
assertThat(isNumeric(null)).isFalse();
assertThat(isNumeric("")).isFalse();
assertThat(isNumeric("abc")).isFalse();
No nosso método isNumeric (), estamos apenas verificando valores do tipo Double, mas esse método também pode ser modificado para verificar Integer, Float, Long __ e grandes números usando qualquer um dos métodos de análise que listamos anteriormente .
Esses métodos também são discutidos no artigo link:/java-string-conversions [Java String Conversions].
3.1. Verificando entradas usando o Scanner
A classe java.util‘s Scanner é talvez a maneira mais fácil no Java comum de obter tipos primitivos de entradas como int, double etc. Ele também fornece APIs diferentes para validar se a entrada fornecida é de um tipo específico ou não.
Por exemplo,* as seguintes APIs verificam se a entrada é do tipo inteiro, longo ou flutuante *:
-
_scanner.hasNextInt () _
-
_scanner.hasNextLong () _
-
_scanner.hasNextFloat () _
Essas APIs retornam true ou false simples com base nos tipos de entrada. Podemos usar essas APIs para garantir que a próxima entrada seja do tipo desejado.
O seguinte trecho verifica se a entrada é um número inteiro ou não:
try (Scanner scanner = new Scanner(System.in)) {
System.out.println("Enter an integer : ");
if (scanner.hasNextInt()) {
System.out.println("You entered : " + scanner.nextInt());
} else {
System.out.println("The input is not an integer");
}
}
Da mesma forma, podemos usar outras APIs para verificar outros tipos.
*4. Usando expressões regulares *
Agora vamos usar a expressão regular -? \ D + (\. \ D +)? para corresponder às Strings numéricas que consistem no número inteiro positivo ou negativo e flutua.
Mas é óbvio que podemos definitivamente modificar esse regex para identificar e lidar com uma ampla variedade de regras. Aqui, vamos simplificar.
Vamos detalhar esse regex e ver como ele funciona:
-
-? _ - esta parte identifica se o número fornecido é negativo, o traço “ – ” pesquisa literalmente o traço e o ponto de interrogação “? _” Marca sua presença como opcional
-
_ \ d + _ - pesquisa um ou mais dígitos *_ (\. \ d +)? _ - esta parte do regex é identificar números flutuantes. Aqui, procuramos um ou mais dígitos seguidos por um ponto. O ponto de interrogação, no final, significa que esse grupo completo é opcional
As expressões regulares são um tópico muito amplo e, para obter uma breve visão geral, visite o link:/regular-expression-java [este artigo vinculado da Baeldung].
Por enquanto, vamos criar um método usando a expressão regular acima:
public static boolean isNumeric(String strNum) {
return strNum.matches("-?\\d+(\\.\\d+)?");
}
Vamos agora ver algumas afirmações para o método acima:
assertThat(isNumeric("22")).isTrue();
assertThat(isNumeric("5.05")).isTrue();
assertThat(isNumeric("-200")).isTrue();
assertThat(isNumeric("abc")).isFalse();
===* 5. Usando o Apache Commons *
Nesta seção, discutiremos vários métodos disponíveis na biblioteca do Apache Commons.
====* 5.1. _NumberUtils.isCreatable (String) _ *
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html [NumberUtils] do Apache Commons fornece um método estático https://commons.apache. org/adequada/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html # isCreatable-java.lang.String- [NumberUtils.isCreatable (String)] que verifica se um _ _ número Java válido ou não.
Este método aceita:
-
Números hexadecimais começando com 0x ou 0X
-
Números octais começando com um 0 inicial
-
Notação científica (por exemplo 1.05e-10)
-
Números marcados com um qualificador de tipo (por exemplo, 1L ou 2.2d)
Se a string fornecida for null ou empty/blank, não será considerada um número e esse método retornará false nesse caso.
Vamos executar alguns testes usando este método:
assertThat(NumberUtils.isCreatable("22")).isTrue();
assertThat(NumberUtils.isCreatable("5.05")).isTrue();
assertThat(NumberUtils.isCreatable("-200")).isTrue();
assertThat(NumberUtils.isCreatable("10.0d")).isTrue();
assertThat(NumberUtils.isCreatable("1000L")).isTrue();
assertThat(NumberUtils.isCreatable("0xFF")).isTrue();
assertThat(NumberUtils.isCreatable("07")).isTrue();
assertThat(NumberUtils.isCreatable("2.99e+8")).isTrue();
assertThat(NumberUtils.isCreatable(null)).isFalse();
assertThat(NumberUtils.isCreatable("")).isFalse();
assertThat(NumberUtils.isCreatable("abc")).isFalse();
assertThat(NumberUtils.isCreatable(" 22 ")).isFalse();
assertThat(NumberUtils.isCreatable("09")).isFalse();
Observe como estamos obtendo declarações verdadeiras para números hexadecimais, números octais e notações científicas nas linhas 6, 7 e 8, respectivamente.
Também na linha 14, a string “09” retorna false porque o “0” anterior indica que este é um número octal e “09” não é um número octal válido.
Para cada entrada que retorna true com esse método, podemos usar https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html#createNumber-java.lang .String - [_ NumberUtils.createNumber (String) _] que nos fornecerá o número válido.
====* 5.2 _NumberUtils.isParsable (String) _ *
O método https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html#isParsable-java.lang.String- [NumberUtils.isParsable (String)] verifica se a String fornecida é analisável ou não.
*Números analisáveis são aqueles analisados com êxito por qualquer método de análise, como _Integer.parseInt (String) _, _Long.parseLong (String) _, __Float.parseFloat (String) __ou _Double.parseDouble (String) _.*
Ao contrário de NumberUtils.isCreatable () _, esse método não aceita números hexadecimais, notações científicas ou seqüências que terminam com qualquer qualificador de tipo, ou seja, ‘f ',‘ F', ‘d ',' D ',' l ' ou‘L' ._
Vejamos algumas afirmações:
assertThat(NumberUtils.isParsable("22")).isTrue();
assertThat(NumberUtils.isParsable("-23")).isTrue();
assertThat(NumberUtils.isParsable("2.2")).isTrue();
assertThat(NumberUtils.isParsable("09")).isTrue();
assertThat(NumberUtils.isParsable(null)).isFalse();
assertThat(NumberUtils.isParsable("")).isFalse();
assertThat(NumberUtils.isParsable("6.2f")).isFalse();
assertThat(NumberUtils.isParsable("9.8d")).isFalse();
assertThat(NumberUtils.isParsable("22L")).isFalse();
assertThat(NumberUtils.isParsable("0xFF")).isFalse();
assertThat(NumberUtils.isParsable("2.99e+8")).isFalse();
Na linha 4, diferentemente de _NumberUtils.isCreatable () _, o número começando com a sequência “0” não é considerado como um número octal, mas como um número decimal normal e, portanto, retorna verdadeiro.
Podemos usar esse método como substituto do que fizemos na seção 3, em que estamos tentando analisar um número e verificar se há um erro.
5.3. StringUtils.isNumeric (CharSequence )
O método https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNumeric-java.lang.CharSequence- [StringUtils.isNumeric (CharSequence)] verifica estritamente para dígitos Unicode. Isso significa:
-
Qualquer dígito de qualquer idioma que seja um dígito Unicode é aceitável
-
Como um ponto decimal não é considerado um dígito Unicode, não é válido
-
Os sinais iniciais (positivos ou negativos) também não são aceitáveis
Vamos agora ver este método em ação:
assertThat(StringUtils.isNumeric("123")).isTrue();
assertThat(StringUtils.isNumeric("١٢٣")).isTrue();
assertThat(StringUtils.isNumeric("१२३")).isTrue();
assertThat(StringUtils.isNumeric(null)).isFalse();
assertThat(StringUtils.isNumeric("")).isFalse();
assertThat(StringUtils.isNumeric(" ")).isFalse();
assertThat(StringUtils.isNumeric("12 3")).isFalse();
assertThat(StringUtils.isNumeric("ab2c")).isFalse();
assertThat(StringUtils.isNumeric("12.3")).isFalse();
assertThat(StringUtils.isNumeric("-123")).isFalse();
Observe que os parâmetros de entrada nas linhas 2 e 3 estão representando os números 123 em árabe e Devanagari, respectivamente. Como são dígitos Unicode válidos, esse método retorna true neles.
5.4 _StringUtils.isNumericSpace (CharSequence) _
O _StringUtils.isNumericSpace(CharSequence) _ verifica estritamente para dígitos Unicode e/ou espaço. Isso é o mesmo que StringUtils.isNumeric () com a única diferença é que ele também aceita espaços, não apenas espaços iniciais e finais, mas também se eles estiverem entre números:
assertThat(StringUtils.isNumericSpace("123")).isTrue();
assertThat(StringUtils.isNumericSpace("١٢٣")).isTrue();
assertThat(StringUtils.isNumericSpace("")).isTrue();
assertThat(StringUtils.isNumericSpace(" ")).isTrue();
assertThat(StringUtils.isNumericSpace("12 3")).isTrue();
assertThat(StringUtils.isNumericSpace(null)).isFalse();
assertThat(StringUtils.isNumericSpace("ab2c")).isFalse();
assertThat(StringUtils.isNumericSpace("12.3")).isFalse();
assertThat(StringUtils.isNumericSpace("-123")).isFalse();
*6. Benchmarks *
Antes de concluirmos este artigo, vamos analisar rapidamente os resultados de benchmark que nos ajudarão a analisar como quais dos métodos mencionados acima são abordagens ideais:
Benchmark Mode Cnt Score Error Units
Benchmarking.usingCoreJava avgt 20 152.061 ± 24.300 ns/op
Benchmarking.usingRegularExpressions avgt 20 1299.258 ± 175.688 ns/op
Benchmarking.usingNumberUtils_isCreatable avgt 20 63.811 ± 5.638 ns/op
Benchmarking.usingNumberUtils_isParsable avgt 20 58.706 ± 5.299 ns/op
Benchmarking.usingStringUtils_isNumeric avgt 20 35.599 ± 8.498 ns/op
Benchmarking.usingStringUtils_isNumericSpace avgt 20 37.010 ± 4.394 ns/op
Como podemos ver, a operação mais cara é com expressões regulares, seguidas pela principal solução baseada em Java. Todas as outras operações usando a biblioteca Apache Commons são em geral iguais.
===* 7. Conclusão*
Neste artigo, exploramos diferentes maneiras de descobrir se uma String é numérica ou não. Examinamos as duas soluções - métodos internos e também bibliotecas externas.
Como sempre, a implementação de todos os exemplos e trechos de código fornecidos acima, incluindo o código usado para realizar benchmarks, pode ser encontrada em https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-string -operações [no GitHub].