1049 votes

Comment vérifier si une chaîne est numérique en Java ?

Comment vérifier si une chaîne est un nombre avant de l'analyser ?

42 votes

Toutes les solutions proposées avec les expresions régulières ne fonctionneront pas pour les nombres hexadécimaux.

0 votes

Et le passage d'une chaîne de caractères nulle dans la fonction matches(...) provoquera une exception NullPointer.

0 votes

Voir la réponse de Max Malysh pour une solution Java 8 concise sans bibliothèques tierces.

1032voto

CraigTP Points 18514

Cela se fait généralement à l'aide d'une simple fonction définie par l'utilisateur (par exemple, la fonction "isNumeric" de Roll-your-own).

Quelque chose comme :

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

Cependant, si vous appelez souvent cette fonction et que vous vous attendez à ce que de nombreuses vérifications échouent parce qu'il ne s'agit pas d'un nombre, les performances de ce mécanisme ne seront pas excellentes, puisque vous comptez sur la levée d'exceptions pour chaque échec, ce qui est une opération assez coûteuse.

Une autre approche peut consister à utiliser une expression régulière pour vérifier la validité d'un nombre :

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

Soyez prudent avec le mécanisme RegEx ci-dessus, car il échouera si vous utilisez des chiffres non arabes (c'est-à-dire des chiffres autres que 0 à 9). Cela est dû au fait que la balise " \d La partie "RegEx" ne correspondra qu'à [0-9] et ne tient pas compte de la dimension numérique internationale. (Merci à OregonGhost de nous l'avoir signalé !)

Une autre alternative consiste à utiliser l'objet java.text.NumberFormat intégré à Java pour voir si, après l'analyse de la chaîne, la position de l'analyseur se trouve à la fin de la chaîne. Si c'est le cas, nous pouvons supposer que la chaîne entière est numérique :

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

8 votes

Fait \d en Java Regex correspondant uniquement aux chiffres latins ? Si c'est comme les regex .NET, vous rencontrerez un problème avec d'autres chiffres (par exemple arabes), comme expliqué ici : blogs.msdn.com/oldnewthing/archive/2004/03/09/86555.aspx

0 votes

@OregonGhost - Oups Bonne prise. Vous avez raison. \d ne correspondra qu'aux chiffres latins (c'est-à-dire de 0 à 9 effectivement) et échouera avec les chiffres arabes. J'ai modifié mon message pour que ce soit plus clair. Merci !

3 votes

La solution numberFormatter n'est probablement que marginalement meilleure que celle consistant à attraper la NumberFormatException. Je pense que la meilleure solution est d'utiliser la méthode regex.

784voto

palacsint Points 9823

Avec Langage Apache Commons 3,5 et plus : NumberUtils.isCreatable o StringUtils.isNumeric .

Avec Langage Apache Commons 3.4 et moins : NumberUtils.isNumber o StringUtils.isNumeric .

Vous pouvez également utiliser StringUtils.isNumericSpace qui renvoie true pour les chaînes vides et ignore les espaces internes de la chaîne. Une autre façon de procéder est d'utiliser NumberUtils.isParsable qui vérifie essentiellement que le nombre est analysable selon Java. (Les javadocs liées contiennent des exemples détaillés pour chaque méthode).

70 votes

StringUtils.isNumeric() ne serait probablement pas approprié ici puisqu'il ne vérifie que si la chaîne est une séquence de chiffres. Cela conviendrait à la plupart des ints, mais pas aux nombres avec des décimales, des séparateurs de groupe, etc.

1 votes

C'est une vieille question mais juste pour ceux qui lisent pour obtenir de l'aide - StringUtils.isNumeric ne fonctionnera pas non plus si la chaîne est vide. StringUtils.isNumeric() retournera true pour une chaîne vide.

2 votes

@JUG : merci pour l'info. Assez étrangement, la doc liée dit le contraire, peut-être à cause d'une version plus récente (notez que la réponse a été modifiée quelques jours seulement après la publication de votre commentaire).

172voto

Ade Alejo Points 323

Si vous êtes sur Android, alors vous devriez utiliser :

android.text.TextUtils.isDigitsOnly(CharSequence str)

La documentation peut être trouvée ici

rester simple . la plupart des gens peuvent "reprogrammer" (la même chose).

5 votes

@kape123 :) bien sûr que "123.456" ne contient pas de chiffres.

10 votes

Remarque : le résultat est un NPE pour une entrée nulle. De plus, elle ne fonctionne pas avec les nombres négatifs ou les décimales.

2 votes

J'aime ça ! Je pense que c'est absolument pour les doigts. Pas pour . , -

134voto

Ibrahim Arief Points 2673

Comme @CraigTP l'avait mentionné dans son excellente réponse, j'ai également des problèmes de performance similaires en utilisant des exceptions pour tester si la chaîne est numérique ou non. Je finis donc par diviser la chaîne et utiliser java.lang.Character.isDigit() .

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

Selon la Javadoc , Character.isDigit(char) reconnaîtra correctement les chiffres non latins. Du point de vue des performances, je pense qu'un simple nombre N de comparaisons, où N est le nombre de caractères de la chaîne, serait plus efficace que de faire une correspondance avec une regex.

MISE À JOUR : Comme l'a fait remarquer Jean-François Corbett dans le commentaire, le code ci-dessus ne validerait que les nombres entiers positifs, ce qui couvre la majorité de mon cas d'utilisation. Voici le code mis à jour qui valide correctement les nombres décimaux selon la locale par défaut utilisée dans votre système, en supposant que le séparateur décimal n'apparaît qu'une seule fois dans la chaîne.

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

4 votes

Le séparateur décimal ne va-t-il pas également provoquer l'échec de l'opération ?

1 votes

@Jean-FrançoisCorbett : Bon point, j'ai mis à jour le code avec un plus récent qui accepte les séparateurs décimaux.

2 votes

Le signe -ve échoue-t-il dans cette fonction ?

44voto

quux00 Points 2496

La bibliothèque Guava de Google fournit une méthode d'aide intéressante pour ce faire : Ints.tryParse . Vous l'utilisez comme Integer.parseInt mais il renvoie null plutôt que de lever une exception si la chaîne n'est pas convertie en un nombre entier valide. Notez qu'il renvoie Integer, et non int, donc vous devez le convertir/autoboxer en 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

Cependant, à partir de la version actuelle -- Guava r11 -- il est toujours marqué @Beta.

Je ne l'ai pas testé. En regardant le code source, il y a une certaine surcharge due à de nombreux contrôles d'intégrité, mais en fin de compte ils utilisent Character.digit(string.charAt(idx)) La réponse de @Ibrahim, similaire, mais légèrement différente, à la réponse de @Ibrahim ci-dessus. Il n'y a pas de surcharge de traitement des exceptions dans leur mise en œuvre.

0 votes

Attention, cela déclencherait un NPE si l'argument est nul.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X