Java: проверьте, является ли строка числом
Строки — это удобный способ передачи информации и получения ввода от пользователя.
В этой статье мы рассмотрим несколько способов проверить, является ли String числовым в Java, то есть представляет ли String числовое значение.
Проверьте, является ли строка числовой с помощью Core Java
Пользователи часто ошибочно набирают входные значения, поэтому разработчики должны как можно дольше держать их за руку во время операций ввода-вывода.
Самый простой способ проверить, является ли String числовым или нет, — использовать один из следующих встроенных методов Java:
- Integer.parseInt()
- Integer.valueOf()
- Double.parseDouble()
- Float.parseFloat()
- Long.parseLong()
Эти методы преобразуют заданную String в ее числовой эквивалент. Если они не могут его преобразовать, NumberFormatException , указывающее, что строка не является числовой.
Стоит отметить, что Integer.valueOf() возвращает new Integer() , а Integer.parseInt() возвращает примитивный int . Имейте это в виду, если такая разница изменит ход вашей программы.
Давайте попробуем это:
Теперь для удобства мы можем абстрагировать эту функциональность во вспомогательный метод:
Теперь мы можем просто позвонить:
Выполнение этого кода приведет к:
С другой стороны, если мы ожидаем, что String будет содержать действительно большое число, мы можем вызвать конструктор BigInteger(String) , который переводит представление String BigInteger .
Проверьте, является ли строка числовой с помощью Apache Commons
Apache Commons — одна из наиболее часто используемых сторонних библиотек для расширения базовой Java Framework. Это дает нам более точный контроль над основными классами Java, в данном случае над строками.
Мы рассмотрим два класса из библиотеки Apache Commons:
- NumberUtils
- StringUtils
Оба из них очень похожи на свои аналоги в классическом Java-классе, но с акцентом на нулевые безопасные операции (с числами и строками соответственно), что означает, что мы можем даже определять значения по умолчанию для отсутствующих ( нулевых ) значений.
Давайте теперь посмотрим, как мы можем проверить числовые значения с помощью этих методов.
NumberUtils.isParsable ()
Этот метод принимает String и проверяет, является ли это число, которое можно анализировать, или нет, мы можем использовать этот метод вместо перехвата исключения при вызове одного из методов, которые мы упоминали ранее.
Это очень хорошо, потому что по возможности следует избегать решений, связанных с частой обработкой исключений — именно в этом нам помогает этот метод.
Обратите внимание, что шестнадцатеричные числа и научные обозначения не считаются анализируемыми.
Теперь нам даже не нужен вспомогательный вспомогательный метод, поскольку isParseable() возвращает само boolean
Этот код должен вернуть:
NumberUtils.isCreatable ()
Этот метод также принимает строку и проверяет, является ли это допустимым номером Java . С помощью этого метода мы можем охватить еще больше чисел, потому что действительный номер Java включает четные шестнадцатеричные и восьмеричные числа, научную нотацию, а также числа, отмеченные квалификатором типа.
Теперь мы даже можем использовать что-то вроде:
NumberUtils.isDigits ()
Метод NumberUtils.isDigits() проверяет, содержит ли строка только цифры Unicode. Если String содержит начальный знак или десятичную точку, метод вернет false :
StringUtils.isNumeric ()
StringUtils.isNumeric() является StringUtils эквивалент NumberUtils.isDigits() .
Если String проходит числовой тест, он все равно может генерировать NumberFormatException при синтаксическом анализе упомянутыми ранее методами, например, если он выходит за пределы диапазона для int или long .
Используя этот метод, мы можем определить, можем ли мы преобразовать String Integer :
StringUtils.isNumericSpace ()
Кроме того, если мы ожидаем найти больше чисел в isNumericSpace , еще один полезный StringUtils стоит упомянуть. Он проверяет, String только цифры или пробелы Unicode.
Давайте проверим строку, содержащую числа и пробелы:
Проверьте, является ли строка числовой с помощью Regex
Несмотря на то, что большинство разработчиков будут довольны использованием уже реализованного метода, иногда у вас может быть очень специфическая проверка шаблона:
А затем мы можем вызвать этот метод:
Выполнение этого дает нам следующий результат:
Заключение
В этой статье мы рассмотрели несколько способов проверить, является ли строка числовой или нет (представляет собой число) в Java.
Мы начали с Core Java и NumberFormatException , после чего использовали библиотеку Apache Commons. Оттуда мы использовали StringUtils и NumberUtils чтобы проверить, является ли String числовым или нет, с различными форматами.
Как определить, является ли строка числом?
Я делал так, но мне кажется такой подход в чем-то неправильным:
![]()
Я так понимаю, цель именно на Integer проверить? Тогда можно:
Если double , но без экспоненциальной нотации, то
такое регулярное подойдёт.
Хотя я бы не парился и сделал бы точно так же, только с Double.parseDouble(s) , но я не показатель 🙂 И ещё я обратил внимание на название метода — оно не очень корректное, т.к. во-первых, такой есть в классе Character , во-вторых, по смыслу подходит isNumeric() . Но это просто комментарии из серии «что я думаю по этому поводу».
Есть очень хороший static-метод в commons-lang (класс NumberUtils ), который учитывает множество особенностей чисел Java:
Метод, описанный в вопросе, и есть самый правильный метод.
Методы, которые проверяют, состоит ли строка лишь из цифр, не справятся с переполнением (попробуйте число 100000000000000000000000000000000 ). Правильный паттерн для целого числа такой:
и поверьте, вам не хочется отлаживать его или адаптировать для других типов.
При этом решения, основанные на паттернах, не будут учитывать локаль и разрешённые разделители разрядов. Так что попробовать распарсить и поймать исключение — практически единственно правильное решение.
![]()
В связи с повышенным интересом по данному вопросу, сделал маленькое исследование 🙂
В исследовании принимали участия классы:
(@VladD, извиняюсь, понимаю, что делает ваш регэксп, но завести его у меня не получилось)
Вывода много, поэтому вкратце:
- абсолютно все строки из примера распарсил только NumberUtils (commons-lang)
- вариант с использованием Guava (расширенный) справился со всем кроме long-нотаций («l») и «0xCAFEBABE» 🙂 (честно, не понимаю, почему он варианты с «f»-нотацией прожевал)
- остальные варианты в большей степени рассчитаны на парсинг именно интов, хотя в изначальном вопросе об этом ни слова 🙂
А вот самое интересное — это время работы данного кода.
Start performance test for core.impl.CharacterDelegator Ints: 125ms Numbers: 67ms Numbers with 25% errors: 50ms Small Ints: 43ms
Start performance test for core.impl.ComplexMatcher Ints: 10825ms Numbers: 11134ms Numbers with 25% errors: 10606ms Small Ints: 10380ms
Start performance test for core.impl.InnerSetImpl Ints: 50ms Numbers: 52ms Numbers with 25% errors: 54ms Small Ints: 42ms
Start performance test for core.impl.NumberUtilsDelegator Ints: 111ms Numbers: 91ms Numbers with 25% errors: 99ms Small Ints: 51ms
Start performance test for core.impl.SimpleMatcher Ints: 1072ms Numbers: 853ms Numbers with 25% errors: 847ms Small Ints: 766ms
Start performance test for core.impl.GuavaDelegator Ints: 131ms Numbers: 108ms Numbers with 25% errors: 124ms Small Ints: 119ms
Start performance test for core.impl.SimpleMatcherWithDot Ints: 3069ms Numbers: 5855ms Numbers with 25% errors: 5484ms Small Ints: 2548ms
Start performance test for core.impl.SimpleParser Ints: 157ms Numbers: 2189ms Numbers with 25% errors: 2117ms Small Ints: 81ms
Start performance test for core.impl.GuavaComplexDelegator Ints: 980ms Numbers: 943ms Numbers with 25% errors: 1016ms Small Ints: 837ms
Тест построен следующим образом
Генерируем 2 рандомных списка со стрингами (числа). Тут есть 4 варианта:
Делаем тестовый прогон на 10_000 элементах.
Из приведенных выкладок видно, что NumberUtils работает быстрее всего. Схожее время работы у простого варианты Guava`ы и простых regexp. Даже добавление простой точки значительно замедляет код. Также замечу, что код @Sergey работает очень быстро, но он рассчитан на проверку строго интов.
А еще есть мой специфический пример InnerSetImpl . Он основан на допущении, что у нас есть ограниченное число возможных вариантов (то есть, мы можем и готовы держать их в памяти). Тогда мы просто помещаем их в HashSet и проверяем наличие строк в нем. Собственно, такой вариант самый быстрый, но допущение многое портит 🙂
ИТОГО: если нужно простое и элегантное решение — то лучше всего воспользоваться NumberUtils.isNumber(str) и не париться.
А если вдруг у вас стоит специфическая задача на парсинг не просто чисел, но чисел в Java-нотациях, то это единственный полностью рабочий вариант.
(Все вышесказанное относится только к приведенному коду. Я не исключаю, что можно придумать (или даже существует) более правильное или более быстрое решение).
Заметки программиста
Этот вопрос возникает наверное у каждого начинающего (и не очень) программиста на java. Есть несколько способов выполнить вышеописанную задачу.
Способ первый — использование метода Integer.parseInt(String string).
Этот способ очень быстро выполняется если строка является числом (в 5-10 раз быстрее, чем способ с использованием регулярных выражений), и очень долго — если строка числом не является (примерно в 1,5 раз дольше, чем способ с использованием регулярных выражений).
Способ второй — использование регулярных выражений.
Этот метод выполняется примерно с одинаковой скоростью вне зависимости от того является ли строка числом.
Способ третий — проверка по очереди каждого символа в строке.
При тестировании данный метод показал на удивление хорошие результаты — более чем в 3 раза быстрее, чем самый быстрый случай для первого и второго метода.
Третий метод и второй для преобрахования строк не подходят, в отличие от первого (при небольшой доработке).
Поэтому если задача стоит только в определении является ли строка числом — то лучше всего подойдет именно третий метод, если же помимо прочего ещё и необходимо преобразовать строку в число то лучше воспользоваться 1 методом, немного видоизменив его.