Блог, посвященный программированию и сисадминистрированию
четверг, 7 июля 2011 г.
Как можно проверить является ли строка числом на java?
Этот вопрос возникает наверное у каждого начинающего (и не очень) программиста на java. Есть несколько способов выполнить вышеописанную задачу.
Способ первый — использование метода Integer.parseInt(String string).
Этот способ очень быстро выполняется если строка является числом (в 5-10 раз быстрее, чем способ с использованием регулярных выражений), и очень долго — если строка числом не является (примерно в 1,5 раз дольше, чем способ с использованием регулярных выражений).
Способ второй — использование регулярных выражений.
Этот метод выполняется примерно с одинаковой скоростью вне зависимости от того является ли строка числом.
Способ третий — проверка по очереди каждого символа в строке.
При тестировании данный метод показал на удивление хорошие результаты — более чем в 3 раза быстрее, чем самый быстрый случай для первого и второго метода.
Третий метод и второй для преобрахования строк не подходят, в отличие от первого (при небольшой доработке).
Поэтому если задача стоит только в определении является ли строка числом — то лучше всего подойдет именно третий метод, если же помимо прочего ещё и необходимо преобразовать строку в число то лучше воспользоваться 1 методом, немного видоизменив его.
Я пишу программу, где пользователь вводит строку в следующем формате:
- мне нужно проверить, что есть число в строке
- а затем извлечь только номер.
- если я использую .contains(«d+») или .contains(«[0-9]+») , программа не может найти число в строке, независимо от того, что вход, но .matches(«d+») будет работать только тогда, когда есть только цифры.
что я могу использовать в качестве решения для поиска и извлечение?
14 ответов:
Если вы хотите извлечь первое число из входной строки, вы можете сделать-
для ввода «123abc», метод выше вернет 123.
для «abc1000def», 1000.
для «555abc45», 555.
для «abc», вернет пустую строку.
s=s.replaceAll(«[*a-zA-Z]», «») заменяет все буквы
s=s.replaceAll(«[*0-9]», «») заменяет все цифры
если вы делаете выше двух заменяет вы получите все специальные charactered string
если вы хотите извлечь только целые числа из String s=s.replaceAll(«[^0-9]», «»)
если вы хотите извлечь только буквы от String s=s.replaceAll(«[^a-zA-Z]», «»)
удачи в кодировании 🙂
Я не смог найти ни одного правильного шаблона. Пожалуйста, следуйте приведенному ниже руководству для небольшого и сладкого решения.
Я думаю, что это быстрее, чем регулярное выражение .
приведенный ниже код достаточно для «проверить, если строка содержит числа в Java»
попробуйте следующий шаблон:
решение, с которым я пошел, выглядит так:
Я уверен, что это не идеальное решение, но это подходит моим потребностям. Спасибо всем за помощь. 🙂
вы можете попробовать это
поскольку вы не только хотите искать число, но и извлекать его, вы должны написать небольшую функцию, делающую это за вас. Идите буква за буквой, пока не найдете цифру. Ах, только что нашел нужный вам код на stackoverflow:найти целое число в строку. Посмотрите на принятый ответ.
.matches(«.*d+.*») работает только для чисел, но не для других символов, таких как // или * etc.
ASCII находится в начале Юникода, так что вы можете сделать что-то вроде этого:
Я уверен, что вы можете выяснить другие ценности.
Я делал так, но мне кажется такой подход в чем-то неправильным:

8 ответов 8
Я так понимаю, цель именно на Integer проверить? Тогда можно:
Если double , но без экспоненциальной нотации, то
такое регулярное подойдёт.
Хотя я бы не парился и сделал бы точно так же, только с Double.parseDouble(s) , но я не показатель 🙂 И ещё я обратил внимание на название метода — оно не очень корректное, т.к. во-первых, такой есть в классе Character , во-вторых, по смыслу подходит isNumeric() . Но это просто комментарии из серии «что я думаю по этому поводу».
Метод, описанный в вопросе, и есть самый правильный метод.
Методы, которые проверяют, состоит ли строка лишь из цифр, не справятся с переполнением (попробуйте число 100000000000000000000000000000000 ). Правильный паттерн для целого числа такой:
и поверьте, вам не хочется отлаживать его или адаптировать для других типов.
При этом решения, основанные на паттернах, не будут учитывать локаль и разрешённые разделители разрядов. Так что попробовать распарсить и поймать исключение — практически единственно правильное решение.

Есть очень хороший static-метод в commons-lang (класс NumberUtils ), который учитывает множество особенностей чисел Java:
Если пишите под android, то можно воспользоваться android.text.TextUtils :

Пока ваше регулярное выражение компилируется.

В связи с повышенным интересом по данному вопросу, сделал маленькое исследование 🙂
В исследовании принимали участия классы:
(@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-нотациях, то это единственный полностью рабочий вариант.
(Все вышесказанное относится только к приведенному коду. Я не исключаю, что можно придумать (или даже существует) более правильное или более быстрое решение).