Як би ви перевірили, чи є рядком число, перш ніж його розбирати?
Integer.parseInt()
, не зможуть проаналізувати мобільні номери NumberFormatException
.
Як би ви перевірили, чи є рядком число, перш ніж його розбирати?
Integer.parseInt()
, не зможуть проаналізувати мобільні номери NumberFormatException
.
Відповіді:
З Apache Commons Lang 3.5 і вище: NumberUtils.isCreatable
або StringUtils.isNumeric
.
З Apache Commons Lang 3.4 і нижче: NumberUtils.isNumber
або StringUtils.isNumeric
.
Ви також можете використовувати StringUtils.isNumericSpace
повернення true
для порожніх рядків і ігнорувати внутрішні пробіли в рядку. Ще один спосіб - це використання, NumberUtils.isParsable
який в основному перевіряє кількість, яке можна проаналізувати відповідно до Java. (Зв'язані javadocs містять докладні приклади для кожного методу.)
StringUtils.isNumeric()
ймовірно, тут не було б доречним, оскільки він перевіряє, чи рядок є послідовністю цифр. Було б добре для більшості вхідних даних, але це не так для цифр із десятковою комою, розділових груп тощо.
StringUtils
не підтримує провідні знаки, але слід перевірити NumberUtils.isCreatable
, чи правильно вони підтримують мінуси.
Як правило, це робиться за допомогою простої функції, визначеної користувачем (тобто функція Roll-your-last "isNumeric").
Щось на зразок:
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e){
return false;
}
}
Однак якщо ви дуже часто викликаєте цю функцію, і ви очікуєте, що багато перевірок вийдуть з ладу через те, що вони не є чисельністю, продуктивність цього механізму не буде великою, оскільки ви покладаєтесь на винятки, які викидаються за кожен збій, що є досить дорогою операцією.
Альтернативним підходом може бути використання регулярного виразу, щоб перевірити справжність числа:
public static boolean isNumeric(String str) {
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
Будьте обережні з вищевказаним механізмом RegEx, оскільки він не вдасться, якщо ви використовуєте неарабські цифри (тобто цифри, від 0 до 9). Це тому, що "\ d" частина RegEx буде відповідати лише [0-9] і фактично не є міжнародною цифрою. (Дякуємо OregonGhost за вказівку на це!)
Або навіть інша альтернатива - використовувати вбудований Java-об’єкт java.text.NumberFormat, щоб побачити, чи після розбору рядка позиція парсера знаходиться в кінці рядка. Якщо це так, ми можемо вважати, що весь рядок є числовим:
public static boolean isNumeric(String str) {
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}
.
у вашому регулярному виразі буде відповідати будь-який символ, а не лише символ десяткового роздільника.
якщо ви перебуваєте на андроїді, то вам слід використовувати:
android.text.TextUtils.isDigitsOnly(CharSequence str)
нехай це буде просто . в основному кожен може «перепрограмувати» (те саме).
.
,-
Java 8 лямбда-вирази.
String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
Як @CraigTP згадував у своїй чудовій відповіді, у мене також є подібні проблеми щодо використання винятків, щоб перевірити, чи є рядок числовим чи ні. Тому я закінчую розбиття рядка та використання java.lang.Character.isDigit()
.
public static boolean isNumeric(String str)
{
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
}
На думку Javadoc , Character.isDigit(char)
правильно розпізнає не латинські цифри. Я думаю, що просте число порівнянь, де N - кількість символів у рядку, було б більш обчислювально ефективнішим, ніж порівняння регулярних виразів.
ОНОВЛЕННЯ: Як зазначив Жан-Франсуа Корбетт у коментарі, вищевказаний код лише підтвердив би додатні цілі числа, що охоплює більшість випадків мого використання. Нижче наведено оновлений код, який правильно перевіряє десяткові числа відповідно до локальної мови за замовчуванням, використовуваної у вашій системі, з припущенням, що десятковий роздільник виникає лише один раз у рядку.
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;
}
toCharArray()
створить копію масиву в об'єкті String, оскільки рядки незмінні. Можливо, швидше використовувати charAt(int index)
метод на об'єкті String безпосередньо.
StringIndexOutOfBoundsException
коли передається рядок з довжиною 0. Може бути встановлена зif(str.length() == 0) return false;
Бібліотека гуави Google забезпечує хороший допоміжний метод , щоб зробити це: Ints.tryParse
. Ви використовуєте його як, Integer.parseInt
але він повертається, null
а не кидає виняток, якщо рядок не аналізує дійсне ціле число. Зауважте, що він повертає Integer, а не int, тому вам доведеться перетворити / автоматично повернути його до int.
Приклад:
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
Однак станом на поточний реліз - Guava r11 - він все ще позначений @Beta.
Я цього не орієнтував. Дивлячись на вихідний код, є деякі накладні витрати з багатьох перевірок на Character.digit(string.charAt(idx))
корисність, але, врешті-решт, вони використовують подібний, але дещо інший, ніж відповідь від @Ibrahim вище. Не є винятком обробка накладних витрат під покривалами при їх виконанні.
Не використовуйте Винятки для перевірки ваших цінностей. Використовуйте Util libs замість апаш NumberUtils:
NumberUtils.isNumber(myStringValue);
Редагувати :
Зауважте, що якщо ваш рядок починається з 0, NumberUtils буде інтерпретувати ваше значення як шістнадцятковий.
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
Number.isNumber()
.
Number.isNumber()
була присутня з першої версії відповіді, датованої 24 вересня 1212 року о 17:01.
Чому всі наполягають на винятку / регулярному вираженні?
Хоча я можу зрозуміти, що більшість людей добре з використанням спроб / лову, якщо ви хочете робити це часто ... це може бути надзвичайно податковою.
Що я тут зробив, це взяти регулярний вираз, методи parseNumber () та метод пошуку масиву, щоб побачити, який був найбільш ефективним. Цього разу я переглянув лише цілі числа.
public static boolean isNumericRegex(String str) {
if (str == null)
return false;
return str.matches("-?\\d+");
}
public static boolean isNumericArray(String str) {
if (str == null)
return false;
char[] data = str.toCharArray();
if (data.length <= 0)
return false;
int index = 0;
if (data[0] == '-' && data.length > 1)
index = 1;
for (; index < data.length; index++) {
if (data[index] < '0' || data[index] > '9') // Character.isDigit() can go here too.
return false;
}
return true;
}
public static boolean isNumericException(String str) {
if (str == null)
return false;
try {
/* int i = */ Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
Результати швидкості, яку я досяг:
Done with: for (int i = 0; i < 10000000; i++)...
With only valid numbers ("59815833" and "-59815833"):
Array numeric took 395.808192 ms [39.5808192 ns each]
Regex took 2609.262595 ms [260.9262595 ns each]
Exception numeric took 428.050207 ms [42.8050207 ns each]
// Negative sign
Array numeric took 355.788273 ms [35.5788273 ns each]
Regex took 2746.278466 ms [274.6278466 ns each]
Exception numeric took 518.989902 ms [51.8989902 ns each]
// Single value ("1")
Array numeric took 317.861267 ms [31.7861267 ns each]
Regex took 2505.313201 ms [250.5313201 ns each]
Exception numeric took 239.956955 ms [23.9956955 ns each]
// With Character.isDigit()
Array numeric took 400.734616 ms [40.0734616 ns each]
Regex took 2663.052417 ms [266.3052417 ns each]
Exception numeric took 401.235906 ms [40.1235906 ns each]
With invalid characters ("5981a5833" and "a"):
Array numeric took 343.205793 ms [34.3205793 ns each]
Regex took 2608.739933 ms [260.8739933 ns each]
Exception numeric took 7317.201775 ms [731.7201775 ns each]
// With a single character ("a")
Array numeric took 291.695519 ms [29.1695519 ns each]
Regex took 2287.25378 ms [228.725378 ns each]
Exception numeric took 7095.969481 ms [709.5969481 ns each]
With null:
Array numeric took 214.663834 ms [21.4663834 ns each]
Regex took 201.395992 ms [20.1395992 ns each]
Exception numeric took 233.049327 ms [23.3049327 ns each]
Exception numeric took 6603.669427 ms [660.3669427 ns each] if there is no if/null check
Відмова: Я не стверджую, що ці методи на 100% оптимізовані, вони лише для демонстрації даних
Винятки вигравали, якщо і лише якщо число становить 4 символи чи менше, а кожен рядок - це завжди число ... у такому випадку навіщо навіть чек?
Коротше кажучи, це надзвичайно боляче, якщо ви часто стикаєтеся з недійсними номерами за допомогою спроби / лову, що має сенс. Важливе правило, якого я завжди дотримуюся, - НІКОЛИ не використовуйте try / catch для потоку програми . Це приклад, чому.
Цікаво, що простий, якщо char <0 || > 9 писати було надзвичайно просто, легко запам'ятовується (і має працювати на декількох мовах) та виграє майже всі тестові сценарії.
Єдиним недоліком є те, що я здогадуюсь, що Integer.parseInt () може обробляти не ASCII номери, тоді як метод пошуку масиву не робить.
Для тих, хто цікавиться, чому я сказав, що легко запам’ятати масив символів один, якщо ви знаєте, що немає негативних ознак, ви можете легко піти з ущільненим таким чином:
public static boolean isNumericArray(String str) {
if (str == null)
return false;
for (char c : str.toCharArray())
if (c < '0' || c > '9')
return false;
return true;
Нарешті, як остаточну ноту, мені було цікаво щодо оператора призначення в прийнятому прикладі з усіма голосами. Додавання у призначенні
double d = Double.parseDouble(...)
це не тільки марно, оскільки ви навіть не використовуєте значення, але це витрачає час на обробку і збільшив час виконання на кілька наносекунд (що призвело до збільшення тестів на 100-200 мс). Я не можу зрозуміти, чому хтось би це зробив, оскільки насправді це додаткова робота щодо зниження продуктивності.
Ви думаєте, що це буде оптимізовано ... хоча, можливо, я повинен перевірити байт-код і подивитися, що робить компілятор. Це не пояснює, чому для мене це завжди виглядало як довше, хоча якщо воно якось оптимізоване ... тому мені цікаво, що відбувається. Як зауваження: Під тривалістю я маю на увазі запуск тесту на 10000000 ітерацій і запуск цієї програми кілька разів (10x +) завжди показав, що вона повільніше.
EDIT: оновлено тест на Character.isDigit ()
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(.\\d+)?");
}
Регулярне вираження CraigTP (показане вище) дає деякі помилкові позитиви. Наприклад, "23y4" буде зараховано до числа, оскільки "." відповідає будь-якому символу, не десятковій крапці.
Крім того, він відхилить будь-яке число за допомогою "+"
Альтернативою, яка дозволяє уникнути цих двох незначних проблем, є
public static boolean isNumeric(String str)
{
return str.matches("[+-]?\\d*(\\.\\d+)?");
}
true
за один плюс "+"
чи мінус "-"
, а false
для"0."
matches("-?\\d+([.]\\d+)?")
Ми можемо спробувати замінити всі числа з даного рядка на (""), тобто порожній пробіл, і якщо після цього довжина рядка дорівнює нулю, то можна сказати, що даний рядок містить лише числа. [Якщо ви вважаєте, що ця відповідь є корисною, тоді, будь ласка, роздумуйте над її голосуванням] Приклад:
boolean isNumber(String str){
if(str.length() == 0)
return false; //To check if string is empty
if(str.charAt(0) == '-')
str = str.replaceFirst("-","");// for handling -ve numbers
System.out.println(str);
str = str.replaceFirst("\\.",""); //to check if it contains more than one decimal points
if(str.length() == 0)
return false; // to check if it is empty string after removing -ve sign and decimal point
System.out.println(str);
return str.replaceAll("[0-9]","").length() == 0;
}
""
це число , але "3.14"
і "-1"
нє?
Ви можете використовувати NumberFormat#parse
:
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
value
.
Якщо ви використовуєте Java для розробки програми для Android, ви можете використовувати функцію TextUtils.isDigitsOnly .
Ось моя відповідь на проблему.
Улов все зручний метод , який можна використовувати для аналізу будь-якого рядка з будь-яким типом парсеру: isParsable(Object parser, String str)
. Аналізатор може бути Class
або object
. Це також дозволяє використовувати власні парсери, які ви написали, і повинні працювати для будь-якого сценарію, наприклад:
isParsable(Integer.class, "11");
isParsable(Double.class, "11.11");
Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");
Ось мій код разом із описами методів.
import java.lang.reflect.*;
/**
* METHOD: isParsable<p><p>
*
* This method will look through the methods of the specified <code>from</code> parameter
* looking for a public method name starting with "parse" which has only one String
* parameter.<p>
*
* The <code>parser</code> parameter can be a class or an instantiated object, eg:
* <code>Integer.class</code> or <code>new Integer(1)</code>. If you use a
* <code>Class</code> type then only static methods are considered.<p>
*
* When looping through potential methods, it first looks at the <code>Class</code> associated
* with the <code>parser</code> parameter, then looks through the methods of the parent's class
* followed by subsequent ancestors, using the first method that matches the criteria specified
* above.<p>
*
* This method will hide any normal parse exceptions, but throws any exceptions due to
* programmatic errors, eg: NullPointerExceptions, etc. If you specify a <code>parser</code>
* parameter which has no matching parse methods, a NoSuchMethodException will be thrown
* embedded within a RuntimeException.<p><p>
*
* Example:<br>
* <code>isParsable(Boolean.class, "true");<br>
* isParsable(Integer.class, "11");<br>
* isParsable(Double.class, "11.11");<br>
* Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");<br>
* isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");<br></code>
* <p>
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @throws java.lang.NoSuchMethodException If no such method is accessible
*/
public static boolean isParsable(Object parser, String str) {
Class theClass = (parser instanceof Class? (Class)parser: parser.getClass());
boolean staticOnly = (parser == theClass), foundAtLeastOne = false;
Method[] methods = theClass.getMethods();
// Loop over methods
for (int index = 0; index < methods.length; index++) {
Method method = methods[index];
// If method starts with parse, is public and has one String parameter.
// If the parser parameter was a Class, then also ensure the method is static.
if(method.getName().startsWith("parse") &&
(!staticOnly || Modifier.isStatic(method.getModifiers())) &&
Modifier.isPublic(method.getModifiers()) &&
method.getGenericParameterTypes().length == 1 &&
method.getGenericParameterTypes()[0] == String.class)
{
try {
foundAtLeastOne = true;
method.invoke(parser, str);
return true; // Successfully parsed without exception
} catch (Exception exception) {
// If invoke problem, try a different method
/*if(!(exception instanceof IllegalArgumentException) &&
!(exception instanceof IllegalAccessException) &&
!(exception instanceof InvocationTargetException))
continue; // Look for other parse methods*/
// Parse method refuses to parse, look for another different method
continue; // Look for other parse methods
}
}
}
// No more accessible parse method could be found.
if(foundAtLeastOne) return false;
else throw new RuntimeException(new NoSuchMethodException());
}
/**
* METHOD: willParse<p><p>
*
* A convienence method which calls the isParseable method, but does not throw any exceptions
* which could be thrown through programatic errors.<p>
*
* Use of {@link #isParseable(Object, String) isParseable} is recommended for use so programatic
* errors can be caught in development, unless the value of the <code>parser</code> parameter is
* unpredictable, or normal programtic exceptions should be ignored.<p>
*
* See {@link #isParseable(Object, String) isParseable} for full description of method
* usability.<p>
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @see #isParseable(Object, String) for full description of method usability
*/
public static boolean willParse(Object parser, String str) {
try {
return isParsable(parser, str);
} catch(Throwable exception) {
return false;
}
}
Щоб відповідати лише позитивним цілим числом десяти, що містить лише цифри ASCII, використовуйте:
public static boolean isNumeric(String maybeNumeric) {
return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}
Хороший підхід, який дозволяє уникнути спроб лову та обробки негативних цифр та наукових позначень.
Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );
public static boolean isNumeric( String value )
{
return value != null && PATTERN.matcher( value ).matches();
}
Ось мій клас перевірки, чи є рядок числовим. Він також фіксує числові рядки:
Ось ви йдете ...
public class NumUtils {
/**
* Transforms a string to an integer. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/
static String makeToInteger(String str) {
String s = str;
double d;
d = Double.parseDouble(makeToDouble(s));
int i = (int) (d + 0.5D);
String retStr = String.valueOf(i);
System.out.printf(retStr + " ");
return retStr;
}
/**
* Transforms a string to an double. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/
static String makeToDouble(String str) {
Boolean dotWasFound = false;
String orgStr = str;
String retStr;
int firstDotPos = 0;
Boolean negative = false;
//check if str is null
if(str.length()==0){
str="0";
}
//check if first sign is "-"
if (str.charAt(0) == '-') {
negative = true;
}
//check if str containg any number or else set the string to '0'
if (!str.matches(".*\\d+.*")) {
str = "0";
}
//Replace ',' with '.' (for some european users who use the ',' as decimal separator)
str = str.replaceAll(",", ".");
str = str.replaceAll("[^\\d.]", "");
//Removes the any second dots
for (int i_char = 0; i_char < str.length(); i_char++) {
if (str.charAt(i_char) == '.') {
dotWasFound = true;
firstDotPos = i_char;
break;
}
}
if (dotWasFound) {
String befDot = str.substring(0, firstDotPos + 1);
String aftDot = str.substring(firstDotPos + 1, str.length());
aftDot = aftDot.replaceAll("\\.", "");
str = befDot + aftDot;
}
//Removes zeros from the begining
double uglyMethod = Double.parseDouble(str);
str = String.valueOf(uglyMethod);
//Removes the .0
str = str.replaceAll("([0-9])\\.0+([^0-9]|$)", "$1$2");
retStr = str;
if (negative) {
retStr = "-"+retStr;
}
return retStr;
}
static boolean isNumeric(String str) {
try {
double d = Double.parseDouble(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
}
Регекс-відповідність
Ось ще один приклад оновленого регулярного вирівнювання «CraigTP» з більшою кількістю перевірок.
public static boolean isNumeric(String str)
{
return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
Тест Regex
1 -- **VALID**
1. -- INVALID
1.. -- INVALID
1.1 -- **VALID**
1.1.1 -- INVALID
-1 -- **VALID**
--1 -- INVALID
-1. -- INVALID
-1.1 -- **VALID**
-1.1.1 -- INVALID
Винятки дорогі, але в цьому випадку RegEx займає набагато більше часу. У наведеному нижче коді показаний простий тест двох функцій - одна з використанням винятків, а одна з використанням регулярного вираження. На моїй машині версія RegEx в 10 разів повільніше, ніж виняток.
import java.util.Date;
public class IsNumeric {
public static boolean isNumericOne(String s) {
return s.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
public static boolean isNumericTwo(String s) {
try {
Double.parseDouble(s);
return true;
} catch (Exception e) {
return false;
}
}
public static void main(String [] args) {
String test = "12345.F";
long before = new Date().getTime();
for(int x=0;x<1000000;++x) {
//isNumericTwo(test);
isNumericOne(test);
}
long after = new Date().getTime();
System.out.println(after-before);
}
}
// перевірте нижче код
public static boolean isDigitsOnly(CharSequence str) {
final int len = str.length();
for (int i = 0; i < len; i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
// only int
public static boolean isNumber(int num)
{
return (num >= 48 && c <= 57); // 0 - 9
}
// is type of number including . - e E
public static boolean isNumber(String s)
{
boolean isNumber = true;
for(int i = 0; i < s.length() && isNumber; i++)
{
char c = s.charAt(i);
isNumber = isNumber & (
(c >= '0' && c <= '9') || (c == '.') || (c == 'e') || (c == 'E') || (c == '')
);
}
return isInteger;
}
// is type of number
public static boolean isInteger(String s)
{
boolean isInteger = true;
for(int i = 0; i < s.length() && isInteger; i++)
{
char c = s.charAt(i);
isInteger = isInteger & ((c >= '0' && c <= '9'));
}
return isInteger;
}
public static boolean isNumeric(String s)
{
try
{
Double.parseDouble(s);
return true;
}
catch (Exception e)
{
return false;
}
}
Це простий приклад для цієї перевірки:
public static boolean isNumericString(String input) {
boolean result = false;
if(input != null && input.length() > 0) {
char[] charArray = input.toCharArray();
for(char c : charArray) {
if(c >= '0' && c <= '9') {
// it is a digit
result = true;
} else {
result = false;
break;
}
}
}
return result;
}
Ви можете використовувати об’єкт java.util.Scanner.
public static boolean isNumeric(String inputData) {
Scanner sc = new Scanner(inputData);
return sc.hasNextInt();
}
Я змінив рішення CraigTP, щоб також прийняти наукові позначення, і крапки, і крапки як десяткові роздільники
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
приклад
var re = new RegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546"); // true
re.test("-6546355e-4456"); // true
re.test("-6546.355e-4456"); // true, though debatable
re.test("-6546.35.5e-4456"); // false
re.test("-6546.35.5e-4456.6"); // false
Ось чому мені подобається підхід Try * у .NET. На додаток до традиційного методу Parse, подібного до Java, у вас є також метод TryParse. Мені непогано в синтаксисі Java (вихідні параметри?), Тому, будь ласка, трактуйте наступне як певний псевдо-код. Це має зробити концепцію зрозумілою.
boolean parseInteger(String s, out int number)
{
try {
number = Integer.parseInt(myString);
return true;
} catch(NumberFormatException e) {
return false;
}
}
Використання:
int num;
if (parseInteger("23", out num)) {
// Do something with num.
}
Проаналізуйте його (тобто з Integer#parseInt
) і просто зловіть виняток. =)
Для уточнення: Функція parseInt перевіряє, чи може вона розібрати число в будь-якому випадку (очевидно), і якщо ви хочете їх розібрати в будь-якому випадку, ви не збираєтесь робити жодних результатів, фактично виконуючи синтаксичний розбір.
Якщо ви не хочете розбирати його (або розбирати його дуже, дуже рідко), можливо, ви хочете зробити це інакше, звичайно.
Ви можете використовувати NumberUtils.isCreatable () від Apache Commons Lang .
Оскільки NumberUtils.isNumber буде застарілим у 4.0, то використовуйте замість NumberUtils.isCreatable ().
Потік Java 8, вираз лямбда, функціональний інтерфейс
Усі оброблені випадки ( нульовий рядок, рядок порожній тощо )
String someString = null; // something="", something="123abc", something="123123"
boolean isNumeric = Stream.of(someString)
.filter(s -> s != null && !s.isEmpty())
.filter(Pattern.compile("\\D").asPredicate().negate())
.mapToLong(Long::valueOf)
.boxed()
.findAny()
.isPresent();
Я проілюстрував деякі умови перевірки чисел і десяткових знаків без використання API,
Перевірте Fix Length 1-значний номер
Character.isDigit(char)
Перевірте номер виправленої довжини (припустимо, довжина становить 6)
String number = "132452";
if(number.matches("([0-9]{6})"))
System.out.println("6 digits number identified");
Перевірте номер між різною довжиною (припустимо, довжина 4 - 6)
// {n,m} n <= length <= m
String number = "132452";
if(number.matches("([0-9]{4,6})"))
System.out.println("Number Identified between 4 to 6 length");
String number = "132";
if(!number.matches("([0-9]{4,6})"))
System.out.println("Number not in length range or different format");
Позначте десятичне число різної довжини між (припустимо, 4 - 7 довжина)
// It will not count the '.' (Period) in length
String decimal = "132.45";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "1.12";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "1234";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "-10.123";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "123..4";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
String decimal = "132";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
String decimal = "1.1";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
Сподіваюсь, що це допоможе багатьом.
На підставі інших відповідей я написав свою власну, і вона не використовує шаблони або синтаксичний аналіз з перевірки виключень.
Він перевіряє максимум один знак мінус і максимум одну десяткову точку.
Ось кілька прикладів та їх результати:
"1", "-1", "-1.5" та "-1.556" повертають істинні
"1..5", "1A.5", "1.5D", "-" і "--1" повертаються помилково
Примітка: Якщо потрібно, ви можете змінити це, щоб прийняти параметр Locale та передати його в виклики DecimalFormatSymbols.getInstance (), щоб використовувати певний Locale замість поточного.
public static boolean isNumeric(final String input) {
//Check for null or blank string
if(input == null || input.isBlank()) return false;
//Retrieve the minus sign and decimal separator characters from the current Locale
final var localeMinusSign = DecimalFormatSymbols.getInstance().getMinusSign();
final var localeDecimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
//Check if first character is a minus sign
final var isNegative = input.charAt(0) == localeMinusSign;
//Check if string is not just a minus sign
if (isNegative && input.length() == 1) return false;
var isDecimalSeparatorFound = false;
//If the string has a minus sign ignore the first character
final var startCharIndex = isNegative ? 1 : 0;
//Check if each character is a number or a decimal separator
//and make sure string only has a maximum of one decimal separator
for (var i = startCharIndex; i < input.length(); i++) {
if(!Character.isDigit(input.charAt(i))) {
if(input.charAt(i) == localeDecimalSeparator && !isDecimalSeparatorFound) {
isDecimalSeparatorFound = true;
} else return false;
}
}
return true;
}
Ось два способи, які можуть працювати. (Без використання винятків). Примітка: Java за замовчуванням є прохідним значенням, а значення String - адреса даних об'єкта String. Отже, коли ти робиш
stringNumber = stringNumber.replaceAll(" ", "");
Ви змінили вхідне значення, щоб не було пробілів. Ви можете видалити цю лінію, якщо хочете.
private boolean isValidStringNumber(String stringNumber)
{
if(stringNumber.isEmpty())
{
return false;
}
stringNumber = stringNumber.replaceAll(" ", "");
char [] charNumber = stringNumber.toCharArray();
for(int i =0 ; i<charNumber.length ;i++)
{
if(!Character.isDigit(charNumber[i]))
{
return false;
}
}
return true;
}
Ось ще один метод у випадку, якщо ви хочете дозволити floats Цей метод нібито дозволяє числам у формі передати 1,123,123,123,123,123.123 я тільки що зробив це, і я думаю, що для його роботи потрібно додаткове тестування.
private boolean isValidStringTrueNumber(String stringNumber)
{
if(stringNumber.isEmpty())
{
return false;
}
stringNumber = stringNumber.replaceAll(" ", "");
int countOfDecimalPoint = 0;
boolean decimalPointPassed = false;
boolean commaFound = false;
int countOfDigitsBeforeDecimalPoint = 0;
int countOfDigitsAfterDecimalPoint =0 ;
int commaCounter=0;
int countOfDigitsBeforeFirstComma = 0;
char [] charNumber = stringNumber.toCharArray();
for(int i =0 ; i<charNumber.length ;i++)
{
if((commaCounter>3)||(commaCounter<0))
{
return false;
}
if(!Character.isDigit(charNumber[i]))//Char is not a digit.
{
if(charNumber[i]==',')
{
if(decimalPointPassed)
{
return false;
}
commaFound = true;
//check that next three chars are only digits.
commaCounter +=3;
}
else if(charNumber[i]=='.')
{
decimalPointPassed = true;
countOfDecimalPoint++;
}
else
{
return false;
}
}
else //Char is a digit.
{
if ((commaCounter>=0)&&(commaFound))
{
if(!decimalPointPassed)
{
commaCounter--;
}
}
if(!commaFound)
{
countOfDigitsBeforeFirstComma++;
}
if(!decimalPointPassed)
{
countOfDigitsBeforeDecimalPoint++;
}
else
{
countOfDigitsAfterDecimalPoint++;
}
}
}
if((commaFound)&&(countOfDigitsBeforeFirstComma>3))
{
return false;
}
if(countOfDecimalPoint>1)
{
return false;
}
if((decimalPointPassed)&&((countOfDigitsBeforeDecimalPoint==0)||(countOfDigitsAfterDecimalPoint==0)))
{
return false;
}
return true;
}