Java String – Смотрите, содержит ли строка только числа, а не буквы
У меня есть строка, которую я загружаю по всему моему приложению, и она изменяется от чисел к буквам и тому подобное. У меня есть простая инструкция if
чтобы увидеть, содержит ли она буквы или цифры, но что-то работает неправильно. Вот fragment.
String text = "abc"; String number; if (text.contains("[a-zA-Z]+") == false && text.length() > 2) { number = text; }
Хотя text
переменная содержит буквы, условие возвращает значение true
. И &&
должны анализировать, поскольку оба условия должны быть true
, чтобы обрабатывать number = text;
==============================
- Почему я не могу написать строковый литерал, в то время как я * могу * написать строковый объект?
- Как я могу форматировать номер строки, чтобы иметь запятые и круглые?
- Как преобразовать байт UTF-8 в строку?
- Почему нет Char.Empty, как String.Empty?
- Как использовать функцию string.substr ()?
Решение:
Я смог решить это, используя следующий код, предоставленный комментарием по этому вопросу. Все остальные сообщения также действительны!
То, что я использовал, работало с первого комментария. Хотя все приведенные примеры кода также являются действительными!
String text = "abc"; String number; if (Pattern.matches("[a-zA-Z]+", text) == false && text.length() > 2) { number = text; }
- wordwrap очень длинная строка
- Неявное преобразование из char ** в const char **
- В чем разница между String и StringBuffer в Java?
- В Java, как я могу анализировать XML как строку вместо файла?
- Как заменить несколько пробелов одним пробелом
- Согласованность hashCode () в строке Java
- Получить OutputStream в строку
- Вычисление частоты каждого слова в предложении в java
Если вы будете обрабатывать номер как текст, измените:
if (text.contains("[a-zA-Z]+") == false && text.length() > 2){
чтобы:
if (text.matches("[0-9]+") && text.length() > 2) {
Вместо проверки того, что строка не содержит буквенных символов, убедитесь, что она содержит только цифры.
Если вы действительно хотите использовать числовое значение, используйте Integer.parseInt()
или Double.parseDouble()
как другие объяснили ниже.
В качестве побочного примечания обычно считается false
практикой сравнивать логические значения с true
или false
. Просто используйте if (condition)
или if (!condition)
.
Вы также можете использовать NumberUtil.isCreatable (String str) из Apache Commons
Вот как я это сделаю:
if(text.matches("^[0-9]*$") && text.length() > 2){ //... }
$
Будет избегать частичного совпадения, например; 1B
.
Производительность parseInt
и такие намного хуже, чем другие решения, поскольку по крайней мере требуют обработки исключений.
Я запустил jmh-тесты и обнаружил, что итерация по String с использованием charAt
и сравнение символов с граничными символами – это самый быстрый способ проверить, содержит ли строка только цифры.
Тест JMH
Тесты сравнивают производительность Character.isDigit
vs. Pattern.matcher().matches
Long.parseLong
vs Long.parseLong
и проверяет значения char.
Эти способы могут приводить к другому результату для строк без ascii и строк, содержащих знаки +/-.
Тесты проходят в режиме пропускной способности ( лучше – лучше ) с 5 итерациями прогрева и 5 тестовыми итерациями.
Результаты
Обратите внимание, что parseLong
почти в 100 раз медленнее, чем isDigit
для первой тестовой нагрузки.
## Test load with 25% valid strings (75% strings contain non-digit symbols) Benchmark Mode Cnt Score Error Units testIsDigit thrpt 5 9.275 ± 2.348 ops/s testPattern thrpt 5 2.135 ± 0.697 ops/s testParseLong thrpt 5 0.166 ± 0.021 ops/s ## Test load with 50% valid strings (50% strings contain non-digit symbols) Benchmark Mode Cnt Score Error Units testCharBetween thrpt 5 16.773 ± 0.401 ops/s testCharAtIsDigit thrpt 5 8.917 ± 0.767 ops/s testCharArrayIsDigit thrpt 5 6.553 ± 0.425 ops/s testPattern thrpt 5 1.287 ± 0.057 ops/s testIntStreamCodes thrpt 5 0.966 ± 0.051 ops/s testParseLong thrpt 5 0.174 ± 0.013 ops/s testParseInt thrpt 5 0.078 ± 0.001 ops/s
Тестирование
@State(Scope.Benchmark) public class StringIsNumberBenchmark { private static final long CYCLES = 1_000_000L; private static final String[] STRINGS = {"12345678901","98765432177","58745896328","35741596328", "123456789a1", "1a345678901", "1234567890 "}; private static final Pattern PATTERN = Pattern.compile("\\d+"); @Benchmark public void testPattern() { for (int i = 0; i < CYCLES; i++) { for (String s : STRINGS) { boolean b = false; b = PATTERN.matcher(s).matches(); } } } @Benchmark public void testParseLong() { for (int i = 0; i < CYCLES; i++) { for (String s : STRINGS) { boolean b = false; try { Long.parseLong(s); b = true; } catch (NumberFormatException e) { // no-op } } } } @Benchmark public void testCharArrayIsDigit() { for (int i = 0; i < CYCLES; i++) { for (String s : STRINGS) { boolean b = false; for (char c : s.toCharArray()) { b = Character.isDigit(c); if (!b) { break; } } } } } @Benchmark public void testCharAtIsDigit() { for (int i = 0; i < CYCLES; i++) { for (String s : STRINGS) { boolean b = false; for (int j = 0; j < s.length(); j++) { b = Character.isDigit(s.charAt(j)); if (!b) { break; } } } } } @Benchmark public void testIntStreamCodes() { for (int i = 0; i < CYCLES; i++) { for (String s : STRINGS) { boolean b = false; b = s.chars().allMatch(c -> c > 47 && c < 58); } } } @Benchmark public void testCharBetween() { for (int i = 0; i < CYCLES; i++) { for (String s : STRINGS) { boolean b = false; for (int j = 0; j < s.length(); j++) { char charr = s.charAt(j); b = '0' <= charr && charr <= '9'; if (!b) { break; } } } } } }
Обновлено 23 февраля 2018 года
- Добавьте еще два случая: один использует
charAt
вместо создания дополнительного массива, а другой - с помощьюIntStream
из кодов символов - Добавьте немедленный разрыв, если не указана цифра для зацикленных тестовых примеров
- Вернуть false для пустой строки для зацикленных тестовых примеров
Обновлено 23 февраля 2018 года
- Добавьте еще один тестовый пример (самый быстрый!), Который сравнивает значение char без использования streamа
Существует множество возможностей для получения чисел из String
s на Java (и наоборот). Вы можете пропустить часть регулярного выражения, чтобы избавить себя от этого.
Например, вы можете попробовать и посмотреть, что Double.parseDouble(String s)
вернется для вас. Он должен NumberFormatException
если оно не находит подходящее значение в строке. Я бы предложил эту технику, потому что вы могли бы фактически использовать значение, представленное String
как числовой тип.
boolean isNum = text.chars (). allMatch (c -> c> = 48 && c <= 57)
Вы можете использовать Regex.Match
if(text.matches("\\d*")&& text.length() > 2){ System.out.println("number"); }
Или вы можете использовать onversions, такие как Integer.parseInt(String)
или лучше Long.parseLong(String)
для больших чисел, например, например:
private boolean onlyContainsNumbers(String text) { try { Long.parseLong(text); return true; } catch (NumberFormatException ex) { return false; } }
И затем проверьте:
if (onlyContainsNumbers(text) && text.length() > 2) { // do Stuff }
Apache Commons Lang предоставляет org.apache.commons.lang.StringUtils.isNumeric(CharSequence cs)
, который принимает в качестве аргумента String
и проверяет, состоит ли она из чисто числовых символов (включая номера из нелатинских скриптов). Этот метод возвращает false
если есть такие символы, как пробел, минус, плюс и десятичные разделители, такие как запятая и точка.
Другие методы этого classа позволяют проводить дополнительные числовые проверки.
Чтобы просто проверить строку, содержащую только ALPHABETS, используйте следующий код:
if (text.matches("[a-zA-Z]+"){ // your operations }
Чтобы просто проверить строку, содержащую только NUMBER, используйте следующий код:
if (text.matches("[0-9]+"){ // your operations }
Надеюсь, это поможет кому-то!
Этот код уже написан. Если вы не возражаете (крайне) незначительный удар производительности, что, вероятно, не хуже, чем выполнение регулярного выражения, используйте Integer.parseInt () или Double.parseDouble () . Это сразу скажет вам, если строка – это только числа (или число, если это необходимо). Если вам нужно обрабатывать более длинные строки чисел, как BigInteger, так и BigDecimal спортивные конструкторы, которые принимают строки. Любой из них будет вызывать исключение NumberFormatException, если вы попытаетесь передать ему не число (целое или десятичное, в зависимости от того, которое вы выберете, конечно). В качестве альтернативы, в зависимости от ваших требований, просто перебирайте символы в строке и проверяйте Character.isDigit () и / или Character.isLetter () .
import java.util.*; class Class1 { public static void main(String[] argh) { boolean ans = CheckNumbers("123"); if (ans == true) { System.out.println("String contains numbers only"); } else { System.out.println("String contains other values as well"); } } public static boolean CheckNumbers(String input) { for (int ctr = 0; ctr < input.length(); ctr++) { if ("1234567890".contains(Character.valueOf(input.charAt(ctr)).toString())) { continue; } else { return false; } } return true; } }
Ниже регулярных выражений можно использовать, чтобы проверить, имеет ли строка только номер или нет:
if (str.matches(".*[^0-9].*")) or if (str.matches(".*\\D.*"))
Оба условия выше вернут true
если String содержит не номера. На false
строка имеет только числа.
Character first_letter_or_number = query.charAt(0); //------------------------------------------------------------------------------ if (Character.isDigit()) { } else if (Character.isLetter()) { }
Рабочий пример тестирования
import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; public class PaserNo { public static void main(String args[]) { String text = "gg"; if (!StringUtils.isBlank(text)) { if (stringContainsNumber(text)) { int no=Integer.parseInt(text.trim()); System.out.println("inside"+no); } else { System.out.println("Outside"); } } System.out.println("Done"); } public static boolean stringContainsNumber(String s) { Pattern p = Pattern.compile("[0-9]"); Matcher m = p.matcher(s); return m.find(); } }
Тем не менее ваш код может быть разбит на «1a» и т. Д., Поэтому вам нужно проверить исключение
if (!StringUtils.isBlank(studentNbr)) { try{ if (isStringContainsNumber(studentNbr)){ _account.setStudentNbr(Integer.parseInt(studentNbr.trim())); } }catch(Exception e){ e.printStackTrace(); logger.info("Exception during parse studentNbr"+e.getMessage()); } }
Метод проверки нет – это строка или нет.
private boolean isStringContainsNumber(String s) { Pattern p = Pattern.compile("[0-9]"); Matcher m = p.matcher(s); return m.find(); }
Плохая практика заключается в том, чтобы задействовать любое исключение броска / обработки в такой типичный сценарий.
Поэтому parseInt () не является хорошим, но регулярное выражение является изящным решением для этого, но позаботьтесь о следующем:
-дробей
неотрицательные числа
-дискальный разделитель может различаться в зависимости (например, ‘,’ или ‘.’)
иногда разрешается иметь так называемый разделитель тысяч, например, пробел или запятую, например, 12 324 1000.55
Чтобы обрабатывать все необходимые случаи в вашем приложении, вы должны быть осторожны, но это регулярное выражение охватывает типичные сценарии (положительные / отрицательные и дробные, разделенные точкой): ^ [- +]? \ D *.? \ D + $
Для тестирования я рекомендую regexr.com .