Форматирование строк или преобразование чисел в строки
Если вы просто хотите преобразовать число в строку в Java, это очень просто с помощью toString (). Возможно, вам придется сначала использовать примитивный тип, например, int, для объекта типа Integer или Double.
// An int. int count = 59; // A float. double cost = 57.59; // Convert int to string and display. System.out.println(new Integer(count).toString()); // Convert float to string and display. System.out.println(new Double(cost).toString());
Если вы хотите больше контроля над форматированием ваших чисел, вам нужен метод static format ().
Этот метод работает так же, как sprintf в C или Perl. Вот пример, который форматирует различные числа:
// An int. int count = 59; // A float. double cost = 57.59; // Format the numbers together with some text. // For 'cost', we make the entire number 7 characters // wide (including the .); we left-pad with zeros // and put two numbers after the decimal point. String text = String.format("Count: %d, Cost: $%07.2f", count, cost); System.out.println(text);
Оцени статью
Оценить
Средняя оценка / 5. Количество голосов:
Видим, что вы не нашли ответ на свой вопрос.
Помогите улучшить статью.
Спасибо за ваши отзыв!
Подстрока (int beginIndex)
Этот метод вернет новый объект String, содержащий подстроку данной строки из указанного startIndex (включительно). Это получит часть String, начинающуюся с заданного beginIndex и до последнего символа String.
Синтаксис таков
public String substring(int beginIndex)
где beginIndex – индекс, с которого начать извлечение возвращаемой подстроки (включительно) Ключевая идея состоит в том, что он получит все символы из индекса, указанного в beginIndex, до последнего символа в строке.
Пример использования Substring в Java
public class SubstringTest { public static void main(String[] args) { String testString = "ABCDEFGHIJ"; System.out.println(testString.substring(0)); System.out.println(testString.substring(1)); System.out.println(testString.substring(2)); System.out.println(testString.substring(3)); System.out.println(testString.substring(4)); System.out.println(testString.substring(5)); System.out.println(testString.substring(6)); System.out.println(testString.substring(7)); System.out.println(testString.substring(8)); System.out.println(testString.substring(9)); } }
А вот вывод приведенного выше кода.
ABCDEFGHIJ BCDEFGHIJ CDEFGHIJ DEFGHIJ EFGHIJ FGHIJ GHIJ HIJ IJ J
Функция SUBSTRING
SUBSTRING (<выражение>, <начальная позиция>, <длина> )
Эта функция позволяет извлечь из выражения его часть заданной длины, начиная от заданной начальной позиции. Выражение может быть символьной или бинарной строкой, а также иметь тип text или image. Например, если нам потребуется получить 3 символа в названии корабля, начиная со 2-го символа, то сделать без помощи функции SUBSTRING будет не так просто. А так мы пишем:
SELECT name, SUBSTRING(name, 2, 3) FROM Ships |
В случае, когда нужно извлечь все символы, начиная с некоторого, мы также можем использовать эту функцию. Например,
SELECT name, SUBSTRING(name, 2, LEN(name)) FROM Ships |
даст нам все символы в названиях кораблей от второй буквы в имени
Обратите внимание на то, что для указания числа извлекаемых символов я использовал функцию LEN(name), которая возвращает число символов в имени. Понятно, что поскольку мне нужны символы, начиная со второго, то их число будет меньше общего количества символов в имени
Однако это не вызывает ошибки, поскольку если указанное число символов превышает возможное число, то будут извлечены все символы до конца строки. Поэтому я и беру их с запасом, не утруждая себя вычислениями.
8 ответов
Решение
Для текстового файла просто перебрать его с петля почти всегда путь. Не говоря уже о скорости, она самая чистая.
В некоторых версиях Python на самом деле просто прочитать одну строку в то время как Цикл читает большие куски и разбивает их на строки, так что это может быть быстрее. Я думаю, что более поздние версии Python используют буферизацию также для поэтому разница в производительности будет крошечной ( вероятно, все еще микроскопически быстрее, потому что он избегает вызова метода). Однако выбор одного из других по соображениям производительности, вероятно, является преждевременной оптимизацией.
Изменить, чтобы добавить: я только что проверил некоторые заметки о выпуске Python. Python 2.5 сказал:
Python 2.6 представил TextIOBase, который поддерживает итерации и одновременно.
Python 2.7 исправлено чередование а также ,
22
2011-02-22 09:04
Если файл огромен, read() — определенно плохая идея, так как он загружает (без параметра размера) весь файл в память.
Readline читает только одну строку за раз, поэтому я бы сказал, что это лучший выбор для больших файлов.
И просто перебор файлового объекта должен быть таким же эффективным, как использование readline.
См. http://docs.python.org/tutorial/inputoutput.html для получения дополнительной информации.
14
2011-02-22 09:03
Документы для readlines указывают на наличие необязательного размера подсказки. Поскольку он настолько расплывчатый, его легко не заметить, но я обнаружил, что часто это самый быстрый способ чтения файлов. Используйте readlines(1), которая намекает на одну строку, но на самом деле читает примерно на 4 или 8 тысяч строк IIRC. Это использует преимущества буферизации ОС и несколько уменьшает количество вызовов без чрезмерного объема памяти.
Вы можете экспериментировать с различными размерами sizehint, но я обнаружил, что 1 был оптимальным на моей платформе, когда я тестировал это
7
2011-02-22 12:03
read() в основном пытается прочитать весь файл и сохранить его в одну строку для последующего использования, в то время как readlines() также пытается прочитать весь файл, но он выполнит разбиение («\n») и сохранит строки строк в список. Следовательно, эти два метода не являются предпочтительными, если размер файла слишком велик.
readline () и цикл for (то есть для строки в файле:) будут читать по одной строке за раз и сохранять ее в строку. Я предполагаю, что они будут использовать то же самое время, чтобы закончить работу, если память позволяет. Однако эти два предпочтительнее, если размер файла огромен.
1
2016-11-07 06:31
Если у вас достаточно памяти, используйте readline, если производительность является проблемой. Я видел это при использовании файла gzip: для прохождения цикла потребовалось 5 секунд, а для использования итератора — 38 секунд. Размер файла GZ был около 45 МБ.
1
2011-05-20 20:06
Если ваш файл представляет собой текстовый файл, тогда используйте readlines(), который, очевидно, является способом чтения файла, содержащего строки. Кроме того: выполните тесты, если вы действительно знаете о возможных проблемах производительности. Я сомневаюсь, что вы столкнетесь с какими-либо проблемами…. скорость файловой системы должна быть ограничивающим фактором.
2011-02-22 09:06
Реальная разница между read() и readlines() Функция read просто загружает файл как есть в память. Метод readlines считывает файл как список строк без завершения строки. Метод readlines должен использоваться только для текстовых файлов, и ни один из них не должен использоваться для больших файлов. Если копировать информацию из текстового файла, read работает хорошо, потому что она может быть выведена с помощью функции write без необходимости добавлять завершение строки.
2015-05-07 06:41
Ни. Оба они будут читать содержимое в память. В случае больших файлов, перебор файлового объекта загружает только одну строку вашего файла за раз и, возможно, является хорошим способом справиться с содержимым огромного файла.
-1
2011-02-22 09:13
2 ответа
Лучший ответ
Таким образом, использует функцию для «многократного чтения» файла. Другие ответы могут более подробно ответить на производительность каждого из них.
-1
llrs
9 Апр 2014 в 08:37
Ради интереса я написал несколько функций, которые перебирают файл и помещают каждую строку в список:
Вот как каждый из них выполнял файл с 69 073 строками с использованием Python 2.6 (обратите внимание, что эти результаты могут отличаться в более новых версиях Python):
Таким образом, readlines () является самым быстрым здесь, хотя итерации по каждой строке с использованием понимания списка почти соответствуют этому. Я предполагаю, что различия в скорости между каждым подходом в основном являются результатом высоких накладных расходов на вызовы функций в Python (чем больше требуется вызовов функций, тем медленнее подход), но могут быть и другие факторы. Надеюсь, кто-то более знающий, чем я, может прокомментировать это.
В дополнение к производительности, еще одним важным фактором при принятии решения о том, какой из этих методов использовать, является стоимость памяти. Использование readlines () приведет к одновременному считыванию всего файла в память. Если вы имеете дело с огромным файлом, это может вызвать серьезные проблемы с производительностью или привести к сбою программы, если вы попытаетесь сразу прочитать все это в памяти. В этих случаях вы хотели бы использовать подход в iterate (), так как он читает только одну строку в памяти за раз. В тех случаях, когда вы просто выполняете какую-то обработку в каждой строке, а затем отбрасываете ее, это обычно — путь, даже если он немного медленнее readlines (), потому что вы не получаете тот же самый удар памяти , Конечно, если ваша цель в конечном итоге — сохранить весь файл в списке Python, вы все равно заплатите эту стоимость памяти, поэтому readlines () будет работать нормально.
19
dano
8 Апр 2014 в 18:29
Разделение
Класс Java String содержит метод split(), который можно использовать для разделения String на массив объектов String:
String source = "A man drove with a car."; String[] occurrences = source.split("a");
После выполнения этого кода Java массив вхождений будет содержать экземпляры String:
"A m" "n drove with " " c" "r."
Исходная строка была разделена на символы a. Возвращенные строки не содержат символов a. Символы a считаются разделителями для деления строки, а разделители не возвращаются в результирующий массив строк.
Параметр, передаваемый методу split(), на самом деле является регулярным выражением Java, которые могут быть довольно сложными. Приведенное выше соответствует всем символам, даже буквам нижнего регистра.
Метод String split() существует в версии, которая принимает ограничение в качестве второго параметра – limit:
String source = "A man drove with a car."; int limit = 2; String[] occurrences = source.split("a", limit);
Параметр limit устанавливает максимальное количество элементов, которое может быть в возвращаемом массиве. Если в строке больше совпадений с регулярным выражением, чем заданный лимит, то массив будет содержать совпадения с лимитом – 1, а последним элементом будет остаток строки из последнего среза – 1 совпадением. Итак, в приведенном выше примере возвращаемый массив будет содержать эти две строки:
"A m" "n drove with a car."
Первая строка соответствует регулярному выражению. Вторая – это остальная часть строки после первого куска.
Выполнение примера с ограничением 3 вместо 2 приведет к тому, что эти строки будут возвращены в результирующий массив String:
"A m" "n drove with " " car."
Обратите внимание, что последняя строка по-прежнему содержит символ в середине. Это потому, что эта строка представляет остаток строки после последнего совпадения (a после ‘n водил с’)
Выполнение приведенного выше примера с пределом 4 или выше приведет к тому, что будут возвращены только строки Split, поскольку в String есть только 4 совпадения с регулярным выражением a.
Присоединение, объединение или добавление строк в Java
Самый простой способ объединить строки в Java – это использовать +. Это работает так:
String text1 = "Hello"; String text2 = "Jim"; System.out.println(text1 + " " + text2);
Однако это не очень эффективно, потому что каждый раз, когда вы пишете +, вы создаете новый объект String. По этой причине вы можете использовать StringBuilder или более старую поточно-ориентированную версию StringBuffer.
StringBuilder sb = new StringBuilder(); sb.append("Hello"); sb.append(" to"); sb.append(" you"); System.out.println(sb.toString());
Более того, поскольку append() возвращает ссылку на сам объект StringBuilder, мы можем написать что-то вроде этого с тем же эффектом:
StringBuilder sb = new StringBuilder(); sb.append("Hello") .append(" to") .append(" you"); System.out.println(sb.toString());
Подстрока Java: выбор частей строк
Чтобы получить часть строки, используйте метод substring.
String substring(int beginIndex, int endIndex)
Длина выбранной подстроки равна endIndex – startIndex.
Вот несколько примеров.
String text = "The quick brown fox"; // Everything from index 4 onwards System.out.println(text.substring(4)); // Index 0 up to but not including index 3. System.out.println(text.substring(0, 3));
Java Array String: объединение массивов строк
Удивительно, но в ядре Java нет способа объединения массивов строк, хотя такие методы существуют в различных библиотеках.
Вы всегда можете создать свои собственные. Следующий класс объявляет именно такой метод и использует его для соединения массива строк. Вы можете легко адаптировать это для работы с ArrayList или Vector или чем-то еще.
package caveofprogramming.aquarium; package caveofprogramming.aquarium; import java.util.*; public class Test { public static String join(String[] strings, String glue) { StringBuilder sb = new StringBuilder(); for(int i=0; i < strings.length; i++) { sb.append(strings); if(i < strings.length - 1) { sb.append(glue); } } return sb.toString(); } public static void main(String [] args) { String texts[] = {"Hello", "to", "you"}; System.out.println(join(texts, " ")); } }
Java String Split: разделение строк
Вы можете разбить строку на массив токенов, используя метод split (REGEX).
Давайте посмотрим на некоторые примеры.
Чтобы разделить пробелом (это также работает для вкладок):
String text = "The quick brown fox"; String text = "The quick brown fox"; // Split on whitespace String [] tokens = text.split("\s+"); for(int i=0; i < tokens.length; i++) { System.out.println(tokens); }
Разделим электронный адрес на части
String text = "someone@nowhere.com"; // Split on @ and . // The double backslashes make this regular // expression look more confusing than it is. // We are escaping once for the sake of the // regex, and again for the sake of Java. String [] tokens = text.split("+"); for(int i=0; i < tokens.length; i++) { System.out.println(tokens); }
Файлы NIO2
Обратите внимание, что в этом руководстве мы будем использовать следующие примерные значения в качестве входного имени файла и общего количества строк:
static final String INPUT_FILE_NAME = "src/main/resources/input.txt"; static final int NO_OF_LINES = 45;
Java 7 внесла множество улучшений в существующие библиотеки ввода-вывода и упаковала их под NIO2:
Давайте начнем с Files и посмотрим, как мы можем использовать его API для подсчета количества строк:
@Test public void whenUsingNIOFiles_thenReturnTotalNumberOfLines() throws IOException { try (Stream fileStream = Files.lines(Paths.get(INPUT_FILE_NAME))) { int noOfLines = (int) fileStream.count(); assertEquals(NO_OF_LINES, noOfLines); } }
Или просто используя метод Files#ReadAllLines :
@Test public void whenUsingNIOFilesReadAllLines_thenReturnTotalNumberOfLines() throws IOException { List fileStream = Files.readAllLines(Paths.get(INPUT_FILE_NAME)); int noOfLines = fileStream.size(); assertEquals(NO_OF_LINES, noOfLines); }
Файловый канал NIO
Теперь давайте проверим FileChannel, высокопроизводительную альтернативу Java NIO для чтения количества строк:
@Test public void whenUsingNIOFileChannel_thenReturnTotalNumberOfLines() throws IOException { int noOfLines = 1; try (FileChannel channel = FileChannel.open(Paths.get(INPUT_FILE_NAME), StandardOpenOption.READ)) { ByteBuffer byteBuffer = channel.map(MapMode.READ_ONLY, 0, channel.size()); while (byteBuffer.hasRemaining()) { byte currentByte = byteBuffer.get(); if (currentByte == '\n') noOfLines++; } } assertEquals(NO_OF_LINES, noOfLines); }
Хотя файловый канал был введен в JDK 4, приведенное выше решение работает только с JDK 7 или выше .
Константы
Если вы используете ту же строку (например, «Hello World») в других объявлениях переменных String, виртуальная машина Java может создать в памяти только один экземпляр String. Таким образом, строковый литерал становится де-факто константой или синглтоном. Различные переменные, инициализированные одной и той же константной строкой, будут указывать на один и тот же экземпляр String в памяти.
String myString1 = "Hello World"; String myString2 = "Hello World";
В этом случае виртуальная машина заставит myString1 и myString2 указывать на один и тот же объект String.
Точнее говоря, объекты, представляющие литералы Java String, получены из пула констант String, который виртуальная машина Java хранит внутри. Это означает, что даже классы из разных проектов, скомпилированные отдельно, но используемые в одном приложении, могут совместно использовать объекты String. Обмен происходит во время выполнения. Это не функция времени компиляции.
Если вы хотите быть уверены, что две строковые переменные указывают на отдельные строковые объекты, используйте оператор new следующим образом:
String myString1 = new String("Hello World"); String myString2 = new String("Hello World");
Даже если значение (текст) двух созданных строк Java одинаково, виртуальная машина Java создаст в памяти два разных объекта для их представления.
Использование StringTokenizer
Простой способ подсчета слов в строке в Java-это использовать класс StringTokenizer :
assertEquals(3, new StringTokenizer("three blind mice").countTokens()); assertEquals(4, new StringTokenizer("see\thow\tthey\trun").countTokens());
Обратите внимание , что StringTokenizer автоматически заботится о пробелах для нас , таких как вкладки и возврат каретки. Но в некоторых местах это может быть неправильно, например, дефисы:
Но в некоторых местах это может быть неправильно, например, дефисы:
assertEquals(7, new StringTokenizer("the farmer's wife--she was from Albuquerque").countTokens());
В этом случае мы хотели бы, чтобы “жена” и “она” были разными словами, но поскольку между ними нет пробелов, значения по умолчанию нас подводят.
К счастью, StringTokenizer поставляется с другим конструктором. Мы можем передать разделитель в конструктор, чтобы выполнить вышеуказанную работу:
assertEquals(7, new StringTokenizer("the farmer's wife--she was from Albuquerque", " -").countTokens());
Это удобно при попытке подсчитать слова в строке из что-то вроде CSV-файла:
assertEquals(10, new StringTokenizer("did,you,ever,see,such,a,sight,in,your,life", ",").countTokens());
Итак, StringTokenizer прост, и он помогает нам в этом большую часть пути.
Давайте посмотрим, какие дополнительные лошадиные силы могут дать нам регулярные выражения.
Форматирование чисел с плавающей точкой Java
%f | Форматируется строка с таким количеством цифр, которое необходимо. Всегда даст вам 6 знаков после запятой |
%.2f | Форматируется строка с таким количеством чисел, которое необходимо. Даст 2 знака после запятой |
%10.2f | Форматируется 2 знаков после запятой, но вся строка займет 10 символов. Если чисел недостаточно, пробелы дополнятся слева от чисел |
Вот несколько примеров кода форматирования строк, целых чисел и чисел с плавающей точкой в Java. Попробуйте их сами.
System.out.printf("%s %d %n", "Общее:", 34573);
Текст «Общее:» будет отформатирован как строка (% s), а цифры 34573 будут отформатированы как цифры (% d):
System.out.printf("%s %10d %n", "Общее:", 34573);
То же, что и выше, только цифры занимают 10 мест с пробелами слева в качестве отступов:
System.out.printf("%-10d %10d %n", 22334, 34573);
Две числа. Первое выровнено по левому краю; второе — по правому:
System.out.printf("%010d %10d %n", 22334, 34573);
Снова два числа. Первое дополнено нулями спереди. Второе — выравнено по правому краю, но пробелы используются как отступы слева вместо нулей:
System.out.printf("%f %n", 345.73);
Отформатировано число с плавающей запятой и добавлены новые строковые символы. Число с плавающей запятой будет иметь 6 знаков после запятой:
System.out.printf("%.2f %n", 34.573);
То же, что и выше, но форматируется только до двух знаков после запятой:
Наконец, вот снова та таблица, которая была вначале этого урока по форматированию в Java:
И вот код для вышеупомянутого форматированного вывода:
package stringformatting; public class StringFormat { public static void main(String args) { String heading1 ="Exam_Name"; String heading2 = "Exam_Grade"; String divider = "-----------------------------------"; String course1 = "Java"; String course2 = "PHP"; String course3 = "VB NET"; String grade1 = "5"; String grade2 = "4"; String grade3 = "3"; System.out.println(""); System.out.printf("%-15s %15s %n", heading1, heading2); System.out.println(divider); System.out.printf("%-15s %10s %n", course1, grade1); System.out.printf("%-15s %10s %n", course2, grade2); System.out.printf("%-15s %10s %n", course3, grade3); System.out.println(divider); System.out.println(""); } }
Поиграйте с форматированием, это пойдет на пользу для закрепления материала. Если вы получаете сообщения об ошибках, возможно, вы перепутали форматирование «s» с форматированием «d»!
В следующем разделе мы продолжим и рассмотрим методы Java.
Использование Внешних Библиотек
Давайте теперь рассмотрим несколько решений, которые используют утилиты из внешних библиотек.
3.1. Использование стрингутилов
В общем, всегда лучше использовать существующее решение, а не изобретать собственное. The commons.lang.Класс StringUtils предоставляет нам метод countMatches () , который может использоваться для подсчета символов или даже подстрок в данной Строке .
Во-первых, нам нужно включить соответствующую зависимость:
org.apache.commonscommons-lang33.11
Мы можем найти последнюю версию на .
Теперь давайте использовать count Matches() для подсчета количества символов e в строковом литерале “слон”.:
int count = StringUtils.countMatches("elephant", "e"); assertEquals(2, count);
3.2. Использование гуавы
Гуава также может быть полезна при подсчете символов. Нам нужно определить зависимость:
com.google.guavaguava21.0
Мы можем найти последнюю версию на .
Давайте посмотрим, как Гуава может быстро помочь нам подсчитать чарс:
int count = CharMatcher.is('e').countIn("elephant"); assertEquals(2, count);
3.3. Использование пружины
Естественно, добавление фреймворка Spring в наш проект только для подсчета символов не имеет смысла.
Однако, если он уже есть в нашем проекте, нам просто нужно использовать метод count вхождений() :
int count = StringUtils.countOccurrencesOf("elephant", "e"); assertEquals(2, count);
Производительность конкатенации
При объединении строк вам следует остерегаться возможных проблем с производительностью. Конкатенация двух строк будет преобразована компилятором Java в нечто вроде этого:
String one = "Hello"; String two = " World"; String three = new StringBuilder(one).append(two).toString();
Создается новый StringBuilder, который передает первую строку в свой конструктор, а вторую – в свой метод append(), прежде чем вызвать метод toString(). Этот код фактически создает два объекта: экземпляр StringBuilder и новый экземпляр String, возвращенный методом toString().
При выполнении самих себя в виде одного оператора эти дополнительные затраты на создание объекта незначительны. Однако когда выполняется внутри цикла, это другая история.
Вот цикл, содержащий вышеуказанный тип конкатенации строк:
String[] strings = new String[]{"one", "two", "three", "four", "five" }; String result = null; for(String string : strings) { result = result + string; }
Этот код будет скомпилирован в нечто похожее на это:
String[] strings = new String[]{"one", "two", "three", "four", "five" }; String result = null; for(String string : strings) { result = new StringBuilder(result).append(string).toString(); }
Теперь для каждой итерации в этом цикле создается новый StringBuilder. Кроме того, объект String создается методом toString(). Это приводит к небольшим расходам на создание экземпляров за одну итерацию: один объект StringBuilder и один объект String. Само по себе не является настоящим убийцей производительности, хотя.
Каждый раз, когда выполняется новый код StringBuilder(result), конструктор StringBuilder копирует все символы из результирующего String в StringBuilder. Чем больше итераций цикла, тем больше будет результат String. Чем больше растет результат String, тем больше времени требуется для копирования символов из него в новый StringBuilder и повторного копирования символов из StringBuilder во временную строку, созданную методом toString(). Другими словами, чем больше итераций, тем медленнее становится каждая итерация.
Самый быстрый способ объединения строк – создать StringBuilder один раз и повторно использовать один и тот же экземпляр внутри цикла. Вот как это выглядит:
String[] strings = new String[]{"one", "two", "three", "four", "five" }; StringBuilder temp = new StringBuilder(); for(String string : strings) { temp.append(string); } String result = temp.toString();
Этот код избегает как экземпляров объектов StringBuilder и String внутри цикла, так и, следовательно, позволяет избежать двухкратного копирования символов, сначала в StringBuilder, а затем снова в String.
Регулярные выражения
Чтобы придумать осмысленное регулярное выражение для этой задачи, нам нужно определить, что мы считаем словом: слово начинается с буквы и заканчивается либо пробелом, либо знаком препинания .
Имея это в виду, учитывая строку, мы хотим разделить эту строку в каждой точке, где мы сталкиваемся с пробелами и знаками препинания, а затем подсчитать полученные слова.
assertEquals(7, countWordsUsingRegex("the farmer's wife--she was from Albuquerque"));
Давайте немного провернем все, чтобы увидеть силу регулярных выражений:
assertEquals(9, countWordsUsingRegex("no&one#should%ever-write-like,this;but:well"));
Нецелесообразно решать эту проблему, просто передавая разделитель в StringTokenizer , так как нам придется определить действительно длинный разделитель, чтобы попытаться перечислить все возможные знаки препинания.
Оказывается, нам действительно не нужно много делать, передавая регулярное выражение ]+ к |/split методу класса String сделает трюк
public static int countWordsUsingRegex(String arg) { if (arg == null) { return 0; } final String[] words = arg.split("]+"); return words.length; }
Регулярное выражение ]+ находит любую длину знаков препинания или пробелов и игнорирует знак препинания апострофа.
Чтобы узнать больше о регулярных выражениях, обратитесь к Регулярным выражениям в Baeldung .