Vérifier si une chaîne est numérique en Java

1. Introduction

Souvent, tout en opérant sur __Strings, nous devons déterminer si un String __est un nombre valide ou non.

  • Dans ce didacticiel, nous explorerons plusieurs manières de détecter si la chaîne _String _ est numérique ** , en utilisant tout d’abord Java, puis les expressions rationnelles et enfin, en utilisant des bibliothèques externes.

Une fois que nous aurons fini de discuter de différentes implémentations, nous utiliserons des points de repère pour avoir une idée des méthodes optimales.

Commençons par quelques prérequis avant de passer au contenu principal.

2. Prérequis

Dans la dernière partie de cet article, nous utiliserons la bibliothèque externe Apache Commons. Pour inclure cette dépendance, ajoutez les lignes suivantes dans pom.xml :

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.7</version>
</dependency>

La dernière version de cette bibliothèque est disponible à l’adresse https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.apache.commons%22%20AND%20a%3A%22commons-lang3 . % 22[Maven Central].

3. Utilisation de Plain Java

Le moyen le plus simple et le plus fiable de vérifier si une chaîne _String _ est numérique ou non consiste à l’analyser à l’aide des méthodes intégrées de Java:

  1. Integer.parseInt (String)

  2. Float.parseFloat (String)

  3. Double.parseDouble (String)

  4. Long.parseLong (String)

  5. new BigInteger (String)

Si ces méthodes ne lancent pas NumberFormatException , cela signifie que l’analyse a réussi et que __String __is numérique:

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

Voyons cette méthode en action:

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();

Dans notre méthode __isNumeric () , nous vérifions simplement les valeurs de type Double , mais cette méthode peut également être modifiée pour rechercher les valeurs Integer , Float , Long __et les grands nombres en utilisant l’une des méthodes d’analyse que nous avons énumérées précédemment .

Ces méthodes sont également décrites dans l’article de lien:/java-string-conversions[Conversions de chaîne Java].

3.1. Vérification des entrées à l’aide de Scanner

La classe Scanner de java.util est peut-être le moyen le plus simple en Java simple d’obtenir des types d’entrée primitifs tels que int , double etc. Elle fournit également différentes API pour valider si l’entrée donnée est d’un type spécifique ou non.

Par exemple, les API suivantes vérifient si l’entrée est de type entier, long ou float :

  • scanner.hasNextInt ()

  • scanner.hasNextLong ()

  • scanner.hasNextFloat ()

Ces API retournent true ou false en fonction des types d’entrée. Nous pouvons utiliser ces API pour nous assurer que la prochaine entrée est du type souhaité.

L’extrait suivant vérifie si l’entrée est un entier ou non:

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

De même, nous pouvons utiliser d’autres API pour vérifier d’autres types.

4. Utilisation d’expressions régulières

Utilisons maintenant les expressions rationnelles __-? \ D (\. \ D)? pour faire correspondre les valeurs numériques Strings __composant de l’entier positif ou négatif et des flottants.

Mais cela va sans dire, nous pouvons définitivement modifier cette expression rationnelle pour identifier et gérer un large éventail de règles. Ici, nous allons garder les choses simples.

Décomposons cette expression rationnelle et voyons comment elle fonctionne:

  • -? - cette partie identifie si le nombre donné est négatif, le tiret

” Recherche littéralement le tiret et le point d’interrogation “ ? ” Marque son présence facultative ** \ d - recherche un ou plusieurs chiffres

  • (\. \ d)? - cette partie de l’expression rationnelle consiste à identifier les nombres flottants. Ici

nous recherchons un ou plusieurs chiffres suivis d’un point. Le point d’interrogation, à la fin, signifie que ce groupe complet est facultatif

Les expressions régulières est un sujet très vaste et pour obtenir un bref aperçu, visitez le lien:/regular-expressions-java[cet article lié à Baeldung].

Pour le moment, créons une méthode utilisant l’expression régulière ci-dessus:

public static boolean isNumeric(String strNum) {
    return strNum.matches("-?\\d+(\\.\\d+)?");
}

Voyons maintenant quelques assertions pour la méthode ci-dessus:

assertThat(isNumeric("22")).isTrue();
assertThat(isNumeric("5.05")).isTrue();
assertThat(isNumeric("-200")).isTrue();

assertThat(isNumeric("abc")).isFalse();

5. Utilisation d’Apache Commons

Dans cette section, nous aborderons diverses méthodes disponibles dans la bibliothèque Apache Commons.

5.1. NumberUtils.isCreatable (String)

__https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html[NumberUtils] de Apache Commons fournit une méthode statique https://commons.apache . org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html # isCreatable-java.lang.String-[NumberUtils.isCreatable (String)] vérifie si un numéro Java valide ou valide ne pas.

Cette méthode accepte:

  1. Nombres hexadécimaux commençant par 0x ou 0X

  2. Nombres octaux commençant par un 0 non significatif

  3. Notation scientifique (par exemple 1.05e-10)

  4. Numéros marqués avec un qualificatif de type (par exemple 1L ou 2.2d)

Si la chaîne fournie est __null or empty/blank , elle n’est pas considérée comme un nombre et cette méthode renvoie false __dans ce cas.

Lançons quelques tests en utilisant cette méthode:

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();

Notez que nous obtenons _assemblées _ vraies inscriptions pour les nombres hexadécimaux, les nombres octaux et les notations scientifiques aux lignes 6, 7 et 8 respectivement.

Également à la ligne 14, la chaîne _ «09» renvoie faux parceque le «0» précédent indique qu’il s’agit d’un nombre octal et que «09» _ n’est pas un nombre octal valide.

Pour chaque entrée renvoyant _true avec cette méthode, nous pouvons utiliser https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html#createNumber-java.lang . .String -[ NumberUtils.createNumber (String) _ ]qui nous donnera le nombre valide.

5.2. NumberUtils.isParsable (String)

Les __https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html#isParsable-java.lang.String-[NumberUtils.isParsable (String)] méthode vérifie si le String __is donné est analysable ou non.

  • Les nombres d’analyse sont ceux qui sont analysés avec succès par une méthode d’analyse telle que Integer.parseInt (String) , Long.parseLong (String) , _Float.parseFloat (String) ou Double.parseDouble (String) _ .

Contrairement à NumberUtils.isCreatable () , cette méthode n’acceptera pas les nombres hexadécimaux, les notations scientifiques ou les chaînes se terminant par un qualificatif de type, par exemple _ 'f', 'F', 'd', 'D', 'l' ou ' L '._

Regardons quelques affirmations:

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();

Dans la ligne 4, contrairement à NumberUtils.isCreatable () , le nombre commençant par la chaîne _ «0» _ n’est pas considéré comme un nombre octal, mais comme un nombre décimal normal et renvoie donc la valeur true.

Nous pouvons utiliser cette méthode pour remplacer ce que nous avons fait à la section 3, dans laquelle nous essayons d’analyser un nombre et de rechercher une erreur.

5.3. _StringUtils.isNumeric (CharSequence ) ___

La méthode _https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNumeric-java.lang.CharSequence-[StringUtils.isNumeric (CharSequence)] _ contrôles strictes pour les chiffres Unicode. Ça signifie:

  1. Tous les chiffres de toutes les langues qui sont des chiffres Unicode sont acceptables

  2. Puisqu’un point décimal n’est pas considéré comme un chiffre Unicode, il n’est pas

valide . Les signes avant-coureurs (positifs ou négatifs) sont également inacceptables

Voyons maintenant cette méthode en action:

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();

Notez que les paramètres d’entrée des lignes 2 et 3 représentent les nombres _123 en arabe et Devanagari respectivement. S’agissant de chiffres Unicode valides, cette méthode renvoie true _ sur eux.

5.4. StringUtils.isNumericSpace (CharSequence)

Https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNumericSpace-java.lang.CharSequence-[ StringUtils.html#isNumericSpace-java.lang.CharSequence-[ StringUtils.isNumericSpace(CharSequence) pour les chiffres et/ou les espaces Unicode. Ceci est identique à _StringUtils.isNumeric () _ avec la seule différence qu’il accepte également les espaces, non seulement les espaces de début et de fin, mais également les espaces entre les nombres:

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

Avant de conclure cet article, passons rapidement en revue les résultats de référence qui nous aideront à analyser laquelle des méthodes mentionnées ci-dessus constitue l’approche optimale:

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

Comme nous pouvons le constater, l’opération la plus coûteuse est l’utilisation d’expressions régulières, suivie de la solution principale basée sur Java. Toutes les autres opérations utilisant la bibliothèque Apache Commons sont généralement les mêmes.

7. Conclusion

Dans cet article, nous avons exploré différentes manières de déterminer si un _String _ est numérique ou non. Nous avons examiné les deux solutions - méthodes intégrées et bibliothèques externes.

Comme toujours, vous pouvez trouver la mise en œuvre de tous les exemples et extraits de code donnés ci-dessus, y compris le code utilisé pour effectuer des tests de performance: over sur GitHub .