Как проверить, является ли строка числовой в Java

Как бы вы проверили, является ли строка числом, прежде чем анализировать ее?


person Craig Angus    schedule 09.07.2009    source источник
comment
Все решения, предложенные с регулярными выражениями, не будут работать с шестнадцатеричными числами.   -  person Oscar Castiblanco    schedule 17.02.2012
comment
и передача нулевой строки в функции match (...) вызовет исключение NullPointer.   -  person Hitesh Sahu    schedule 14.04.2016
comment
См. Ответ Макса Малыша для краткого решения Java 8 без сторонних библиотек.   -  person Andy Thomas    schedule 28.04.2016
comment
Нулевые строки @HiteshSahu, похоже, изящно обрабатываются в последней версии (включая Java 6.x и 7.x)   -  person lifebalance    schedule 06.10.2016
comment
Все решения, предлагаемые для использования Integer.parseInt(), не смогут анализировать мобильные номера с NumberFormatException.   -  person Not a bug    schedule 16.03.2017
comment
@OscarCastiblanco Все строки - это числа в заданном основании.   -  person bfontaine    schedule 30.05.2018


Ответы (36)


С Apache Commons Lang 3.5 и выше: _ 1_ или StringUtils.isNumeric.

С Apache Commons Lang 3.4 и ниже: _ 3_ или StringUtils.isNumeric.

Вы также можете использовать _ 5_, который возвращает true для пустых строк и игнорирует внутренние пробелы в строке. Другой способ - использовать _ 7_, который в основном проверяет, является ли число доступным для синтаксического анализа в соответствии с Java. (Связанные документы javadoc содержат подробные примеры для каждого метода.)

person palacsint    schedule 24.09.2012
comment
StringUtils.isNumeric(), вероятно, здесь не подходит, поскольку он проверяет только, является ли строка последовательностью цифр. Подойдет для большинства целых чисел, но не для чисел с десятичными знаками, разделителями групп и т. Д. - person Jeff Mercado; 09.02.2013
comment
Довольно старый вопрос, но только для тех, кто читает за помощью - StringUtils.isNumeric не будет работать также, если это пустая строка. Он вернет true для пустой строки для StringUtils.isNumeric (). - person JUG; 01.03.2013
comment
@JUG: спасибо за внимание. Как ни странно, связанный документ говорит об обратном, возможно, из-за более новой версии (обратите внимание, что ответ был отредактирован всего через несколько дней после публикации вашего комментария) - person Adrien Be; 05.02.2014
comment
@JUG: искал в нем, и вот что я подумал, некоторые предыдущие версии, т.е. Commons Lang версии 2.4 stringutils.isNumeric () ведет себя так, как вы сказали (верните true для пустой строки) - person Adrien Be; 05.02.2014
comment
изобретать велосипед, потому что вы не включаете целую библиотеку, потому что вам нужна трехстрочная функция в одном месте. - person dalvarezmartinez1; 18.09.2014
comment
Но действительно ли стоит добавлять всю библиотеку для этой функции? Очевидно, что если он используется с другими вещами, это здорово, но, вероятно, это излишне, учитывая, что люди решили это в одной строке кода. - person Water; 30.03.2015
comment
Почему isNumeric возвращает true для вопросительных знаков? commons.apache.org/proper/commons-lang/apidocs/org/apache/ - person pete; 15.07.2016
comment
@pete: Эти вопросительные знаки кажутся цифрами Деванагари (которые, вероятно, не поддерживаются нашими шрифтами / браузером). См .: issues.apache.org/jira/browse/LANG-1017. - person palacsint; 15.07.2016
comment
Не работает с негативами. И половина всех чисел отрицательная, так что ..... - person Paul Draper; 30.06.2017
comment
@PaulDraper: Вы правы, StringUtils не поддерживает ведущие знаки, но вы должны проверить NumberUtils.isCreatable, он правильно поддерживает негативы. - person palacsint; 01.07.2017
comment
Добавление зависимости, чтобы проверить, является ли строка числом ... Вау - person GabrielBB; 21.11.2018
comment
NumberUtils.isParsable (String str) можно использовать для проверки, является ли данная строка числовой, что будет работать для всех сценариев. - person ajith george; 25.01.2019
comment
Вот все способы: baeldung.com/java-check-string-number - person Anchor; 10.07.2019

Обычно это делается с помощью простой пользовательской функции (например, функции Roll-your-own 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 регулярного выражения будет соответствовать только [0-9] и фактически не имеет международной числовой информации. (Спасибо OregonGhost за указание на это!)

Или даже другой альтернативой является использование встроенного в Java объекта java.text.NumberFormat, чтобы увидеть, находится ли после анализа строки позиция анализатора в конце строки. Если это так, мы можем предположить, что вся строка является числовой:

public static boolean isNumeric(String str) {
  ParsePosition pos = new ParsePosition(0);
  NumberFormat.getInstance().parse(str, pos);
  return str.length() == pos.getIndex();
}
person CraigTP    schedule 09.07.2009
comment
Соответствует ли \ d в Java Regex только латинским цифрам? Если это похоже на регулярные выражения .NET, вы столкнетесь с проблемой с другими (например, арабскими) цифрами, как описано здесь: blogs.msdn.com/oldnewthing/archive/2004/03/09/86555.aspx - person OregonGhost; 09.07.2009
comment
@OregonGhost - Ой ... Хороший улов. Ты прав. \ d будет соответствовать только латинским цифрам (то есть от 0 до 9 эффективно) и не будет соответствовать арабским. Я отредактировал свой пост, чтобы прояснить это. Спасибо! - person CraigTP; 09.07.2009
comment
решение numberFormatter, вероятно, лишь ненамного лучше, чем перехват исключения NumberFormatException. Я подозреваю, что лучший способ - использовать регулярное выражение. - person Chii; 09.07.2009
comment
Обратите внимание, что . в вашем регулярном выражении будет соответствовать любому символу, а не только символу десятичного разделителя. - person jqno; 11.07.2009
comment
+1 за осознание затрат на попытку / улов. На самом деле это ужасный подход для использования в долгосрочной перспективе для многократного использования, но на самом деле мы застряли в Java. - person demongolem; 06.09.2011
comment
Я бы использовал регулярное выражение (\\+|-)?\\d+(\\.\\d+)?, поскольку "+1.20" - допустимое числовое значение. - person Buhake Sindi; 04.05.2012
comment
В последнем предложении (NumberFormat) вам не хватает проверки на null в методе синтаксического анализа. В противном случае isNumeric () вернет true, поскольку индекс позиции останется неизменным! - person JBE; 27.08.2012
comment
Для обработки экспоненты (+ 1.3E10): return str.matches("\\d") && str.matches("^[+-]?\\d*\\.?\\d*([eE]\\d)?\\d*$"); - person fchen; 20.12.2012
comment
Имейте в виду, что: Double.parseDouble (NaN) ‹- не бросает и исключение. - person xgMz; 10.09.2013
comment
также не забывайте .006 и 0. - они тоже действительны. - person ; 06.11.2013
comment
Оба решения плохи, если использовать их расширяемо. Создание исключения обходится дорого, и создание регулярных выражений также требует больших затрат. Регулярное выражение необходимо создать один раз и использовать повторно. - person Daniel Nuriyev; 03.02.2014
comment
@ user1096901 Мне хорошо известны последствия использования исключений для проверки данных, и я даже говорю, почему это не обязательно лучший подход в моем ответе. Затем я предлагаю альтернативы, которые, вероятно, являются лучшими. Все подходы детализированы, чтобы дать максимально полный и взвешенный ответ. - person CraigTP; 30.09.2014
comment
@fchen, правильная идея, но за буквой «E» в научных обозначениях также может следовать «+» или «-». - person Derek Mahar; 28.04.2015
comment
В этом случае RegEx в 10 раз медленнее, чем обработка исключения. Убедитесь сами, используя код в моем ответе ниже. - person ChrisCantrell; 18.06.2015
comment
Великолепно, даже работает с иностранными номерами, такими как гуджарати (૧૦૦), астурийский (২০১৯), тибетский (৬৫), бенгальский (႑), иврит (8), японский (15), кхмерский (២០១៥), скажем так, большинство - person Danielson; 08.10.2015
comment
что, если строка 2.2E8 - person xiaoyifang; 23.10.2015
comment
Что, если в строке используется другой десятичный разделитель, например ,? - person Eduardo Naveda; 26.11.2015
comment
@Eddnav Первый подход (с использованием Double.parseDouble) не будет работать для чисел с разными десятичными разделителями, однако последний подход, показанный в моем ответе (с использованием класса java.text.NumberFormat), правильно работает для альтернативных десятичных разделителей (по крайней мере, работает для запятой). См. Здесь: ideone.com/vaOEae - person CraigTP; 27.11.2015
comment
Обратите внимание, что латинских цифр не существует, а цифры 0–9 на самом деле являются арабскими цифрами. Люди, вероятно, знакомы с римскими цифрами, которые использовались людьми, говорившими на латыни, в форме I, II, III, IV, V, VI и т. Д. en.wikipedia.org/wiki/Arabic_numerals; en.wikipedia.org/wiki/Roman_numerals - person dantiston; 05.03.2016
comment
Выполните это (Double.parseDouble и regex) по сравнению с преобразованием строки в char [] и запуском isDigit над ним, а также с запуском char [] вместо массива допустимых символов. Сравнение проводилось по времени работы с System.nanoTime (). Все они получили примерно одно и то же: строка длиной 2500 символов либо без цифр, либо по крайней мере с одной цифрой. - person Ungeheuer; 16.02.2017
comment
первый числовой с: double d = Double.parseDouble (str); возвращает истину, если строка имеет вид 0F :-) - person Giovesoft; 05.10.2017
comment
Совершенно очевидно, что бессмысленно вызывать Integer.parseInt() дважды на одном и том же входе. Правильное решение - вызвать его один раз, когда это необходимо, и уловить и обработать NumberFormatException по мере его возникновения. - person user207421; 12.11.2017
comment
Именно так (ваш первый подход) я сделал это при создании математического парсера около 11 лет назад. Вы можете найти проект на странице github.com/gbenroscience/ParserNG. - person gbenroscience; 28.05.2020

если у вас Android, то вам следует использовать:

android.text.TextUtils.isDigitsOnly(CharSequence str)

можно найти здесь

будь простым. в основном каждый может «перепрограммировать» (то же самое).

person Ahmed Alejo    schedule 22.11.2013
comment
@ kape123 :) конечно, 123.456 не содержит цифр. - person Ahmed Alejo; 14.11.2014
comment
Примечание: это приводит к NPE для нулевого ввода. Также не работает с отрицательными числами или десятичными знаками. - person gMale; 19.12.2014
comment
Мне это нравится!! Думаю, это абсолютно для цифр. Не для ., - - person illusionJJ; 13.09.2016
comment
Это как раз то, что я искал. Что-то простое, чтобы проверить только цифры 0-9. Я установил фильтр в объявлении моего EditText, но на тот случай, если он будет изменен или заменен в будущем, неплохо также иметь простую программную проверку. - person jwehrle; 26.06.2018

Лямбда-выражения Java 8.

String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
person Max Malysh    schedule 13.12.2015
comment
Вы также можете использовать ссылку на метод: someString.chars (). AllMatch (Character :: isDigit) - person Wienczny; 08.02.2016
comment
Приятно, но все же здесь заново изобретают колесо, как и почти все решения. Кроме того, не работает при нулевом значении (как и почти все остальные). - person qben; 24.03.2016
comment
Это краткий, простой и читаемый ответ. Вы можете читать его почти как английский - все символы соответствуют цифрам. Не требует сторонних библиотек. В неисключительных случаях исключения не используются. Это должно стать принятым ответом. - person Andy Thomas; 28.04.2016
comment
Что он даст за -1? - person Balázs Németh; 28.06.2016
comment
@AndyThomas для строки чисел длиной 5135 символов занимает 169,424,664 наносекунды или 169,424664 миллисекунды (на моей машине). Это слишком неэффективно. Вы можете получить 15 мсек или меньше, запустив вложенный цикл for для сравнения символов с допустимыми символами char []. - person Ungeheuer; 16.02.2017
comment
@ Адриан, вот эталон: gist.github.com/maxmalysh/8f656be2843b7c35849a 9 мс для строки длиной 1 миллион символов. 169 мс для строки длиной 5 тыс. Символов - это слишком необычно. - person Max Malysh; 16.02.2017
comment
@Adrian - Во вселенной из 10 ^ 80 атомов не так много полезных 5135-значных чисел. Если строки-кандидаты могут быть длинными, можно предварительно провести проверку длины. Может потребоваться оптимизация. Это также может быть преждевременным. Правильность может быть более серьезной проблемой. Стоит отметить, что этот ответ (и некоторые другие) обнаруживают только положительные целые числа. Он потерпит неудачу, если потребуется обнаружить отрицательные числа, действительные числа, шестнадцатеричные числа, научную нотацию ... - person Andy Thomas; 16.02.2017
comment
Не правильный ответ. Числовая строка может содержать нечисловые символы (например, или -) и при этом быть полностью числовой. Например, 0,5, -1 и 1000 все равно не дадут этот ответ, но все же они полностью числовые. - person Simeon G; 24.04.2018
comment
Он не работает ни с отрицательными числами, ни с десятичными числами. - person yuvi; 01.05.2018

Как упомянул @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, где 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;
}
person Ibrahim Arief    schedule 17.08.2011
comment
Знак -ve не работает с этой функцией? - person java_mouse; 29.05.2013
comment
Я думаю, что это должен быть принятый ответ, потому что это самое легкое решение. Использование исключения или регулярного выражения очень сложно проверить, является ли строка числовой. Перебирать символы - это приятно и просто! - person W.K.S; 01.12.2013
comment
Приведенный выше код принимает один "-" как числовой и вернет true. измените сначала if на что-нибудь вроде: boolean isMinus = str.charAt(0) == localeMinusSign; if ((isMinus && str.length() < 2) || ((!isMinus) && !Character.isDigit(str.charAt(0)))) { return false; } - person coder; 26.12.2013
comment
Вызов toCharArray() создаст копию массива в объекте String, потому что строки неизменяемы. Вероятно, быстрее использовать метод charAt(int index) для объекта String напрямую. - person Mike Kucera; 09.10.2014
comment
Будет генерировать StringIndexOutOfBoundsException при передаче строки длины 0. Может быть исправлено с помощью if(str.length() == 0) return false; - person samgak; 25.02.2016

Библиотека Google Guava предоставляет для этого хороший вспомогательный метод: Ints.tryParse. Вы используете его как Integer.parseInt, но он возвращает null, а не генерирует исключение, если строка не преобразуется в действительное целое число. Обратите внимание, что он возвращает Integer, а не int, поэтому вам нужно преобразовать / autobox его обратно в 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 выше. В их реализации нет накладных расходов на обработку исключений.

person quux00    schedule 29.01.2012
comment
Помните, что это вызовет NPE, если аргумент равен нулю. - person Vadzim; 18.06.2019

Не используйте исключения для проверки своих значений. Вместо этого используйте библиотеки Util, например apache NumberUtils:

NumberUtils.isNumber(myStringValue);

Изменить:

Обратите внимание: если ваша строка начинается с 0, NumberUtils интерпретирует ваше значение как шестнадцатеричное.

NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
person Goot    schedule 31.08.2015
comment
Принятый ответ, принятый тремя годами ранее, уже касался Number.isNumber(). - person Andy Thomas; 28.04.2016
comment
Я так не думаю. Он был обновлен или op изменил принятый ответ. Я помню, что принятый ответ не охватывал NumberUtils, поэтому я добавил свой ответ. Но спасибо за комментарий - person Goot; 29.04.2016
comment
@Goot - История принятого ответа показывает, что Number.isNumber() присутствовал в первой версии ответа, датированной 24 сентября 2012 года, 17:01. - person Andy Thomas; 16.02.2017
comment
@Goot, это неплохо, поскольку оно также охватывает проверку десятичных значений, в отличие от StringUtils. - person Heena Hussain; 02.02.2018

Почему все настаивают на решениях исключений / регулярных выражений?

Хотя я понимаю, что большинству людей нравится использовать try / catch, если вы хотите делать это часто ... это может оказаться чрезвычайно утомительным.

Здесь я взял регулярное выражение, методы 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, что имеет смысл. Я всегда следую важному правилу: НИКОГДА не используйте команду try / catch для выполнения программы. Это пример того, почему.

Интересно, что простой if char ‹0 || > 9 было чрезвычайно просто написать, легко запомнить (и должно было работать на нескольких языках), и он побеждает почти во всех тестовых сценариях.

Единственным недостатком является то, что я предполагаю, что Integer.parseInt () может обрабатывать числа, отличные от ASCII, тогда как метод поиска по массиву - нет.


Для тех, кто задается вопросом, почему я сказал, что легко запомнить массив символов 1, если вы знаете, что нет отрицательных знаков, вы можете легко уйти от чего-то сжатого, например:

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 +) всегда показывал, что он был медленнее.

РЕДАКТИРОВАТЬ: обновлен тест для Character.isDigit ()

person Water    schedule 29.03.2015
comment
Разве это не компилирует каждый раз новое регулярное выражение? Это кажется не очень эффективным. - person Samuel Edwin Ward; 11.06.2015
comment
@SamuelEdwinWard Это вся причина, по которой я написал этот пост ... в примере с регулярным выражением использовались ответы других людей, и он показал, насколько он неэффективен. Даже если вы попытаетесь предварительно скомпилировать регулярное выражение и использовать только его, разница во времени составит: 2587 мс для регулярного выражения, которое я опубликовал от других предоставленных людей, 950 мс при предварительной компиляции, 144 мс при выполнении его как числовой массив (для 1 мил итераций одной и той же строки). Предварительная компиляция, очевидно, поможет, но, к сожалению, она все еще уступает способу массива ... если нет какой-то безумной оптимизации, о которой я не знаю. - person Water; 12.06.2015
comment
Вера в то, что Regex ускоряет работу, - почти заблуждение. Если это разовый поиск, да, я понимаю ... но я заметил, что эффективно написанный код на самом деле превосходит регулярное выражение, чтобы вас шокировать! Отличный пост @Water - person Yo Apps; 16.10.2019

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

Регулярное выражение CraigTP (показанное выше) дает несколько ложных срабатываний. Например. «23y4» будет засчитано как число, потому что '.' соответствует любому символу, кроме десятичной точки.

Также он отклонит любое число с начальным знаком "+"

Альтернативой, позволяющей избежать этих двух незначительных проблем, является

public static boolean isNumeric(String str)
{
    return str.matches("[+-]?\\d*(\\.\\d+)?");
}
person user872985    schedule 17.09.2011
comment
это вернет true для одного плюса "+" или минус "-" и false для "0." - person user85421; 17.09.2011
comment
Хороший улов на одном плюсе-минусе. 0. - действительное число? - person user872985; 18.09.2011
comment
"0." действителен для Double.parseDouble() и является допустимым литералом в соответствии с JLS (§3.10.2)! - person user85421; 18.09.2011
comment
Создание регулярных выражений также требует больших затрат. Регулярное выражение необходимо создать один раз и использовать повторно. - person Daniel Nuriyev; 03.02.2014
comment
вы должны изменить его на matches("-?\\d+([.]\\d+)?") - person Bobs; 05.01.2016
comment
Кроме того, это соответствует пустой строке. [+-]?(\\d\\.)?\\d+ должно работать лучше - person Solomon Ucko; 14.06.2017
comment
Почему каждое решение Regex предполагает, что формат Local Decimal представляет собой '.' (Точка), а не ',' (запятая), как в некоторых странах ЕС ?! - person Yo Apps; 16.10.2019

Мы можем попробовать заменить все числа в данной строке на (), т.е. пробел, и если после этого длина строки будет равна нулю, то мы можем сказать, что данная строка содержит только числа. Пример:

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;
    }
person Ketan Ramteke    schedule 29.10.2018
comment
Итак, "" - это число, а "3.14" и "-1" - нет? - person Eric Duminil; 28.03.2019
comment
Очевидно, не относится ко всем числовым формам, но вот голос за то, чтобы думать иначе ... если исходная мысль была вашей, то есть. - person gbenroscience; 28.05.2020
comment
Он действительно отлично работает. - person Chema; 22.04.2021

Вы можете использовать NumberFormat#parse :

try
{
     NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
    // Not a number.
}
person Artem Barger    schedule 09.07.2009
comment
Предложено редактирование - отсутствует .getInstance (). +1 так как это был ответ, на который я пришел, когда нашел этот вопрос. - person 8bitjunkie; 10.04.2012
comment
Дорого при расширенном использовании - person Daniel Nuriyev; 03.02.2014
comment
Он также пройдет, если в конце value есть символы мусора. - person Brian White; 26.02.2014
comment
Если вы не регистрируете исключение, возникнет проблема с сонаром. - person jmhostalet; 12.04.2018
comment
Это сработало для числового формата 0x0001, где Double.parseDouble не работал. +1 - person Seabass77; 16.08.2018

Если вы используете Java для разработки приложения для Android, вы можете использовать TextUtils. isDigitsOnly.

person Eric Guo    schedule 25.02.2014

Вот мой ответ на проблему.

Удобный метод catch all, который можно использовать для синтаксического анализа любой строки с любым типом синтаксического анализатора: 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;
    }
}
person Jamie Bell    schedule 28.11.2011

Хорошо работающий подход, позволяющий избежать ловушек и обрабатывать отрицательные числа и научную запись.

Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );

public static boolean isNumeric( String value ) 
{
    return value != null && PATTERN.matcher( value ).matches();
}
person lars    schedule 17.03.2014

Соответствие регулярных выражений

Вот еще один пример обновленного соответствия регулярного выражения "CraigTP" с большим количеством проверок.

public static boolean isNumeric(String str)
{
    return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
  1. Допускается только один отрицательный знак -, и он должен быть в начале.
  2. После знака минус должна быть цифра.
  3. Допускается только один десятичный знак ..
  4. После десятичного знака должна быть цифра.

Тест регулярного выражения

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
person Madan Sapkota    schedule 15.06.2015

Чтобы сопоставить только положительные целые числа с основанием десять, которые содержат только цифры ASCII, используйте:

public static boolean isNumeric(String maybeNumeric) {
    return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}
person user11153    schedule 14.08.2014

Вот мой класс для проверки, является ли строка числовой. Он также исправляет числовые строки:

Функции:

  1. Удаляет ненужные нули ["12.0000000" -> "12"]
  2. Удаляет ненужные нули ["12.0580000" -> "12.058"]
  3. Удаляет нечисловые символы ["12.00sdfsdf00" -> "12"]
  4. Обрабатывает отрицательные строковые значения ["-12,020000" -> "-12.02"]
  5. Удаляет несколько точек ["-12.0.20.000" -> "-12.02"]
  6. Никаких дополнительных библиотек, только стандартная Java

Ну вот...

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

}
person Meatball    schedule 07.10.2014

Исключения обходятся дорого, но в этом случае 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);

}

}
person ChrisCantrell    schedule 18.06.2015
comment
Как правило, я думаю, что такой код можно использовать для проверки таких вещей, как ввод с клавиатуры. В этом случае скорость не рассматривается, и делать что-то столь же уродливое, как создание исключения для проверки числа или не числа, является неправильным. - person user872985; 07.08.2015
comment
Может быть нет. Типизированный ввод обычно проверяется компонентом пользовательского интерфейса, где ошибки могут отображаться сразу перед отправкой значения. Возможно, более распространенным является проверка строк из больших входных текстовых файлов - там, где важна производительность. Цель моего ответа здесь - решить, что исключения - это медленное утверждение в принятом ответе. Сложное регулярное выражение намного дороже. И в моем коде вообще нет уродливого броска - просто более быстрый способ обнаружения нарушений. При использовании подхода «сначала проверка, затем расчет» вы выполняете два прохода через входные данные: один для проверки, а затем другой для преобразования. - person ChrisCantrell; 08.08.2015

// пожалуйста, проверьте код ниже

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;
}
person Tejas Parmar    schedule 16.09.2016
comment
В вопросе указано числовое значение, которое может включать нецелочисленные значения. - person rghome; 16.09.2016

Вы можете использовать объект java.util.Scanner.

public static boolean isNumeric(String inputData) {
      Scanner sc = new Scanner(inputData);
      return sc.hasNextInt();
    }
person Yu Wai Hlaing    schedule 19.08.2015

Это простой пример этой проверки:

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;
}
person ARIJIT    schedule 15.09.2014

Я проиллюстрировал некоторые условия для проверки чисел и десятичных знаков без использования какого-либо API,

Проверить длину исправления 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");

Надеюсь, это поможет многим.

person ArifMustafa    schedule 11.06.2018

Основываясь на других ответах, я написал свой собственный, и он не использует шаблоны или синтаксический анализ с проверкой исключений.

Он проверяет максимум один знак минус и проверяет максимум одну десятичную точку.

Вот несколько примеров и их результаты:

«1», «-1», «-1,5» и «-1,556» возвращают значение true.

«1..5», «1A.5», «1.5D», «-» и «--1» возвращают false

Примечание. При необходимости вы можете изменить это, чтобы принять параметр языкового стандарта и передать его в вызовы DecimalFormatSymbols.getInstance (), чтобы использовать конкретный языковой стандарт вместо текущего.

 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;
}
person Josh Gager    schedule 18.12.2018

Я изменил решение 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
person AndyTheEntity    schedule 05.12.2013

Вот почему мне нравится подход 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.
}
person OregonGhost    schedule 09.07.2009
comment
да, в Java нет выходных параметров, и поскольку оболочка Integer неизменяема (поэтому не может использоваться в качестве действительной ссылки для хранения вывода), разумным идиоматическим вариантом будет возврат объекта Integer, который может быть нулевым, если синтаксический анализ завершился неудачно. Более уродливым вариантом может быть передача int [1] в качестве выходного параметра. - person fortran; 09.07.2009
comment
Да, я помню обсуждение того, почему Java не имеет выходных параметров. но возвращение Integer (как null, если необходимо) тоже было бы хорошо, я думаю, хотя я не знаю о производительности Java в отношении упаковки / распаковки. - person OregonGhost; 09.07.2009
comment
Мне нравится C # так же, как и всем остальным, но бесполезно добавлять фрагмент кода .NET C # для вопроса Java, когда в Java нет функций. - person Shane; 28.01.2015
comment
Если вы не регистрируете исключение, возникнет проблема с сонаром. - person jmhostalet; 12.04.2018

Разберите его (т.е. с помощью Integer#parseInt) и просто перехватите исключение. знак равно

Чтобы уточнить: функция parseInt проверяет, может ли она анализировать число в любом случае (очевидно), и если вы все равно хотите его проанализировать, вы не собираетесь снижать производительность, фактически выполняя синтаксический анализ.

Если вы не хотите анализировать его (или анализировать очень и очень редко), вы, конечно, можете сделать это по-другому.

person gha.st    schedule 09.07.2009
comment
Дорого при расширенном использовании - person Daniel Nuriyev; 03.02.2014
comment
Если вы не регистрируете исключение, возникнет проблема с сонаром. - person jmhostalet; 12.04.2018
comment
Double.parseDouble - person Alex78191; 04.12.2018

Вы можете использовать NumberUtils.isCreatable () из Apache Commons Lang .

Поскольку NumberUtils.isNumber будет устаревшим в версии 4.0, используйте вместо него NumberUtils.isCreatable ().

person Cenxui    schedule 13.11.2016

Java 8 Stream, лямбда-выражение, функциональный интерфейс

Все дела обработаны (строка пуста, строка пуста и т. Д.)

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();
person Noor Nawaz    schedule 11.05.2016

Я думаю, что единственный способ надежно определить, является ли строка числом, - это проанализировать ее. Поэтому я бы просто проанализировал его, и если это число, вы получите число в int бесплатно!

person jqno    schedule 09.07.2009

Вот два метода, которые могут сработать. (Без использования исключений). Примечание. 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;
}

Вот еще один метод на случай, если вы хотите разрешить поплавки. Этот метод якобы позволяет числам в форме передавать 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;
}
person XForCE07    schedule 19.04.2013
comment
О, хороший вопрос. Я предполагаю, что этот работает только с целыми числами обычного типа. Изначально метод был создан для фильтрации входных телефонных номеров и подсчета номеров. - person XForCE07; 20.04.2013

Вы можете использовать BigDecimal, если строка может содержать десятичные знаки:

try {
    new java.math.BigInteger(testString);
} catch(NumberFormatException e) {
    throw new RuntimeException("Not a valid number");
}
person Dayanand    schedule 06.04.2012
comment
Добро пожаловать в stackoverflow. Как правило, лучше не восстанавливать старые потоки, если ответ не добавляет к потоку что-то существенно отличающееся. Хотя этот подход действителен, этот подход уже упоминался в принятом ответе. - person Leigh; 07.04.2012
comment
Если вы не регистрируете исключение, возникнет проблема с сонаром. - person jmhostalet; 12.04.2018

Если вы хотите выполнить проверку с использованием регулярного выражения, вы должны создать окончательный статический объект Pattern, таким образом, регулярное выражение необходимо скомпилировать только один раз. Компиляция регулярного выражения занимает примерно столько же времени, сколько и выполнение сопоставления, поэтому, приняв эту меру предосторожности, вы сократите время выполнения метода вдвое.

final static Pattern NUMBER_PATTERN = Pattern.compile("[+-]?\\d*\\.?\\d+");

static boolean isNumber(String input) {
    Matcher m = NUMBER_PATTERN.matcher(input);
    return m.matches();
}

Я предполагаю, что число представляет собой строку, в которой нет ничего, кроме десятичных цифр, возможно, знак + или - в начале и не более одной десятичной точки (не в конце) и никаких других символов (включая запятые, пробелы, числа в другие системы счета, римские цифры, иероглифы).

Это краткое и довольно быстрое решение, но вы можете сэкономить пару миллисекунд на миллион вызовов, сделав это следующим образом

static boolean isNumber(String s) {
    final int len = s.length();
    if (len == 0) {
        return false;
    }
    int dotCount = 0;
    for (int i = 0; i < len; i++) {
        char c = s.charAt(i);
        if (c < '0' || c > '9') {
            if (i == len - 1) {//last character must be digit
                return false;
            } else if (c == '.') {
                if (++dotCount > 1) {
                    return false;
                }
            } else if (i != 0 || c != '+' && c != '-') {//+ or - allowed at start
                return false;
            }

        }
    }
    return true;
}
person mikeyreilly    schedule 07.08.2014

Попробуй это:

public  boolean isNumber(String str)
{       
    short count = 0;
    char chc[]  = {'0','1','2','3','4','5','6','7','8','9','.','-','+'};
    for (char c : str.toCharArray())
    {   
        for (int i = 0;i < chc.length;i++)
        {
            if( c  == chc[i]){
                count++;        
            }
         }                      
    }
    if (count != str.length() ) 
        return false;
    else
        return true;
}
person Hans van Kraaij    schedule 23.01.2015

Параллельная проверка очень длинных строк с помощью IntStream

В Java 8 следующие тесты проверяют, находятся ли все символы данного string в пределах от «0» до «9». Помните, что пустая строка принимается:

string.chars().unordered().parallel().allMatch( i -> '0' <= i && '9' >= i )
person Bernhard Bodenstorfer    schedule 24.05.2018

Это самый быстрый способ проверить, является ли строка числом или нет:

public static boolean isNumber(String str){
  int i=0, len=str.length();
  boolean a=false,b=false,c=false, d=false;
  if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-')) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; a=true; }
  if(i<len && (str.charAt(i)=='.')) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; b=true; }
  if(i<len && (str.charAt(i)=='e' || str.charAt(i)=='E') && (a || b)){ i++; c=true; }
  if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-') && c) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; d=true;}
  return i==len && (a||b) && (!c || (c && d));
}
static boolean isDigit(char c){
  return c>='0' && c<='9';
}
person user3870075    schedule 09.04.2017
comment
Вместо множества проверок мы можем просто использовать if (ch ›= '0' && ch‹ = '9') {} - person jettimadhuChowdary; 28.11.2019

Если вы, ребята, используете следующий метод для проверки:

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

Тогда что случилось с вводом очень длинной строки, такой как я называю этот метод:

System.out.println(isNumeric("94328948243242352525243242524243425452342343948923"));

Результат "верный", также это слишком большое число! То же самое произойдет, если вы используете регулярное выражение для проверки! Поэтому я бы предпочел использовать метод "синтаксического анализа" для проверки, например:

public static boolean isNumeric(String str) {
    try {
        int number = Integer.parseInt(str);
        return true;
    } catch (Exception e) {
        return false;
    }
}

И результат - то, что я ожидал!

person Tạ Anh Tú    schedule 18.09.2018
comment
это число слишком большого размера → Не существует такого понятия, как число слишком большого размера. Числа бесконечны. 7645 - это число, а 92847294729492875982452012471041141990140811894142729051 - тоже число. Первый может быть представлен как Integer, а второй - как BigDecimal. И даже если они не могут быть представлены как объект в Java, они все равно являются числами - вот что задается вопросом. - person walen; 18.09.2018
comment
Кроме того, не злоупотребляйте исключениями. Java - это не питон. По крайней мере, используйте более конкретный NumberFormatException - person Jiří; 13.12.2018