Java String - voir si une chaîne de caractères ne contient que des nombres et non des lettres
j'ai une chaîne que je charge tout au long de ma demande, et il change de chiffres en Lettres et autres. J'ai une simple déclaration if
pour voir si elle contient des lettres ou des chiffres mais, quelque chose ne fonctionne pas tout à fait correctement. Voici un extrait de code.
String text = "abc";
String number;
if (text.contains("[a-zA-Z]+") == false && text.length() > 2) {
number = text;
}
bien que la variable text
contienne des lettres, la condition retourne comme true
. Le et &&
devrait être évalué comme les deux conditions devant être true
afin de traiter le number = text;
==============================
Solution:
j'ai pu résoudre ce problème en utilisant le code suivant fourni par un commentaire sur cette question. Tous les autres postes sont valables aussi bien!
ce que j'ai utilisé qui a fonctionné est issu du premier commentaire. Bien que tous les codes d'exemple fournis semblent être valables aussi!
String text = "abc";
String number;
if (Pattern.matches("[a-zA-Z]+", text) == false && text.length() > 2) {
number = text;
}
16 réponses
si vous traitez le numéro comme texte, puis changer:
if (text.contains("[a-zA-Z]+") == false && text.length() > 2){
à:
if (text.matches("[0-9]+") && text.length() > 2) {
au lieu de vérifier que la chaîne ne ne contient pas de caractères alphabétiques, vérifiez pour être sûr qu'elle contient seulement numerics.
Si vous voulez utiliser la valeur numérique, utiliser Integer.parseInt()
ou Double.parseDouble()
comme d'autres l'ont expliqué ci-dessous.
comme note latérale, il est généralement considéré comme une mauvaise pratique de comparer les valeurs booléennes à true
ou false
. Il suffit d'utiliser if (condition)
ou if (!condition)
.
vous pouvez également utiliser NumberUtil.isCreatable (String) from Apache Commons
C'est comment j'allais le faire:
if(text.matches("^[0-9]*$") && text.length() > 2){
//...
}
le $
évitera une correspondance partielle E. g; 1B
.
Performance-wise parseInt
et tels sont beaucoup plus worser que d'autres solutions, parce qu'au moins exigent la manipulation d'exception.
j'ai effectué des tests jmh et j'ai trouvé que l'itération sur la chaîne de caractères en utilisant charAt
et en comparant les caractères avec les caractères limites est le moyen le plus rapide de tester si la chaîne de caractères ne contient que des chiffres.
JMH testing
Tests de comparer les performances des Character.isDigit
vs Pattern.matcher().matches
vs Long.parseLong
vs vérification des valeurs de char.
ces méthodes peuvent produire des résultats différents pour les chaînes non ascii et les chaînes contenant des signes+/ -.
Essais exécutés en mode de débit ( plus grand est mieux ) avec 5 itérations d'échauffement et 5 itérations d'essai.
résultats
noter que parseLong
est presque 100 fois plus lent que isDigit
pour la première charge d'essai.
## Test load with 25% valid strings (75% strings contain non-digit symbols)
Benchmark Mode Cnt Score Error Units
testIsDigit thrpt 5 9.275 ± 2.348 ops/s
testPattern thrpt 5 2.135 ± 0.697 ops/s
testParseLong thrpt 5 0.166 ± 0.021 ops/s
## Test load with 50% valid strings (50% strings contain non-digit symbols)
Benchmark Mode Cnt Score Error Units
testCharBetween thrpt 5 16.773 ± 0.401 ops/s
testCharAtIsDigit thrpt 5 8.917 ± 0.767 ops/s
testCharArrayIsDigit thrpt 5 6.553 ± 0.425 ops/s
testPattern thrpt 5 1.287 ± 0.057 ops/s
testIntStreamCodes thrpt 5 0.966 ± 0.051 ops/s
testParseLong thrpt 5 0.174 ± 0.013 ops/s
testParseInt thrpt 5 0.078 ± 0.001 ops/s
Test suite
@State(Scope.Benchmark)
public class StringIsNumberBenchmark {
private static final long CYCLES = 1_000_000L;
private static final String[] STRINGS = {"12345678901","98765432177","58745896328","35741596328", "123456789a1", "1a345678901", "1234567890 "};
private static final Pattern PATTERN = Pattern.compile("\d+");
@Benchmark
public void testPattern() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
b = PATTERN.matcher(s).matches();
}
}
}
@Benchmark
public void testParseLong() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
try {
Long.parseLong(s);
b = true;
} catch (NumberFormatException e) {
// no-op
}
}
}
}
@Benchmark
public void testCharArrayIsDigit() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
for (char c : s.toCharArray()) {
b = Character.isDigit(c);
if (!b) {
break;
}
}
}
}
}
@Benchmark
public void testCharAtIsDigit() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
for (int j = 0; j < s.length(); j++) {
b = Character.isDigit(s.charAt(j));
if (!b) {
break;
}
}
}
}
}
@Benchmark
public void testIntStreamCodes() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
b = s.chars().allMatch(c -> c > 47 && c < 58);
}
}
}
@Benchmark
public void testCharBetween() {
for (int i = 0; i < CYCLES; i++) {
for (String s : STRINGS) {
boolean b = false;
for (int j = 0; j < s.length(); j++) {
char charr = s.charAt(j);
b = '0' <= charr && charr <= '9';
if (!b) {
break;
}
}
}
}
}
}
mis à jour le 23 février 2018
- ajouter deux cas supplémentaires - un en utilisant
charAt
au lieu de créer un tableau supplémentaire et un autre en utilisantIntStream
de codes de caractères - ajouter rupture immédiate si aucun chiffre n'a été trouvé pour les cas d'essai en boucle
- Return false pour une chaîne vide pour la boucle en cas de test
mis à jour le 23 février 2018
- Ajouter un cas d'essai de plus (le plus rapide!) qui compare la valeur de char sans utiliser stream
il existe de nombreuses possibilités pour obtenir des numéros de String
s en Java (et vice versa). Vous pouvez ignorer les regex partie de vous épargner la complication.
par exemple, vous pouvez essayer et voir ce que Double.parseDouble(String s)
retourne pour vous. Il faut jeter un NumberFormatException
s'il ne trouve pas une valeur appropriée dans la chaîne. Je suggère cette technique parce que vous pouvez réellement faire usage de la valeur représentée par le String
en tant que type numérique.
vous pouvez utiliser Regex.Match
if(text.matches("\d*")&& text.length() > 2){
System.out.println("number");
}
ou vous pouvez utiliser des versions comme Integer.parseInt(String)
ou mieux Long.parseLong(String)
pour des nombres plus grands
comme par exemple:
private boolean onlyContainsNumbers(String text) {
try {
Long.parseLong(text);
return true;
} catch (NumberFormatException ex) {
return false;
}
}
et ensuite tester avec:
if (onlyContainsNumbers(text) && text.length() > 2) {
// do Stuff
}
Apache Commons Lang provides org.apache.commons.lang.StringUtils.isNumeric(CharSequence cs)
, qui prend comme argument un String
et vérifie s'il se compose de caractères purement numériques (y compris les nombres de caractères non latins). Cette méthode retourne false
s'il y a des caractères comme espace, moins, plus, et des séparateurs décimaux comme virgule et point.
D'autres méthodes de cette classe permettent d'autres vérifications numériques.
pour vérifier simplement la chaîne qu'elle contient seulement des ALPHABETS utilisez le code suivant:
if (text.matches("[a-zA-Z]+"){
// your operations
}
pour vérifier simplement la chaîne de caractères QU'elle ne contient que le numéro, utilisez le code suivant :
if (text.matches("[0-9]+"){
// your operations
}
Espérons que cela aidera à quelqu'un!
ce code est déjà écrit. Si vous ne faites pas attention à la performance (extrêmement) mineure hit--qui n'est probablement pas pire que de faire une correspondance regex--utilisez entier.parseInt() ou Double.parseDouble () . Cela vous dira tout de suite si une chaîne de caractères n'est que des nombres (ou est un nombre , selon le cas). Si vous avez besoin de manipuler des chaînes de nombres plus longues, à la fois BigInteger et BigDecimal les constructeurs sportifs qui acceptent les cordes. N'importe lequel de ceux-ci lancera un NumberFormatException si vous essayez de lui passer un non-nombre (intégrale ou décimale, basée sur celle que vous choisissez, bien sûr). Alternativement, selon vos besoins, il suffit d'itérer les caractères dans la chaîne et de cocher caractère.Isdigit () et/ou .isLetter () .
import java.util.*;
class Class1 {
public static void main(String[] argh) {
boolean ans = CheckNumbers("123");
if (ans == true) {
System.out.println("String contains numbers only");
} else {
System.out.println("String contains other values as well");
}
}
public static boolean CheckNumbers(String input) {
for (int ctr = 0; ctr < input.length(); ctr++) {
if ("1234567890".contains(Character.valueOf(input.charAt(ctr)).toString())) {
continue;
} else {
return false;
}
}
return true;
}
}
ci-dessous regexs peut être utilisé pour vérifier si une chaîne a seulement le nombre ou pas:
if (str.matches(".*[^0-9].*")) or if (str.matches(".*\D.*"))
les deux conditions ci-dessus retourneront true
si la chaîne contient des non-nombres. Sur false
, la chaîne n'a que des nombres.
Character first_letter_or_number = query.charAt(0);
//------------------------------------------------------------------------------
if (Character.isDigit())
{
}
else if (Character.isLetter())
{
}
exemple D'essai de fonctionnement
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
public class PaserNo {
public static void main(String args[]) {
String text = "gg";
if (!StringUtils.isBlank(text)) {
if (stringContainsNumber(text)) {
int no=Integer.parseInt(text.trim());
System.out.println("inside"+no);
} else {
System.out.println("Outside");
}
}
System.out.println("Done");
}
public static boolean stringContainsNumber(String s) {
Pattern p = Pattern.compile("[0-9]");
Matcher m = p.matcher(s);
return m.find();
}
}
toujours votre code peut être cassé par " 1a "etc donc vous devez vérifier l'exception
if (!StringUtils.isBlank(studentNbr)) {
try{
if (isStringContainsNumber(studentNbr)){
_account.setStudentNbr(Integer.parseInt(studentNbr.trim()));
}
}catch(Exception e){
e.printStackTrace();
logger.info("Exception during parse studentNbr"+e.getMessage());
}
}
méthode de vérification de la chaîne de caractères no is
private boolean isStringContainsNumber(String s) {
Pattern p = Pattern.compile("[0-9]");
Matcher m = p.matcher(s);
return m.find();
}
c'est une mauvaise pratique d'inclure toute exception de lancer/manipulation dans un tel scénario typique.
par conséquent un parseInt () n'est pas agréable, mais un regex est une solution élégante pour cela, mais prendre soin de ce qui suit:
- fractions
- nombres négatifs
- le séparateur décimal peut différer dans le contenu (par exemple", "ou".')
-parfois, il est autorisé à avoir un séparateur de milliers, comme un espace ou une virgule Par exemple 12,324,1000.355
pour traiter tous les cas nécessaires dans votre application, vous devez être prudent, mais ce regex couvre les scénarios typiques (positif / négatif et fractionnaire, séparé par un point): ^[ -+]?\d*.?\d+$
pour les tests, je recommande regexr.com .
Voici mon code, j'espère que cela vous aidera !
public boolean isDigitOnly(String text){
boolean isDigit = false;
if (text.matches("[0-9]+") && text.length() > 2) {
isDigit = true;
}else {
isDigit = false;
}
return isDigit;
}