Строки в Java: работа с классом String. Practical Tasks
Вызов text.replace("a", "o"); компилируется и выполняется без ошибок, но text после него остаётся прежним: строки в Java неизменяемы, а новая строка-результат просто теряется. Такие промахи быстрее всего ловятся на практике — ради неё и собраны задачи ниже.
На этой странице — 13 практических задач по строкам в Java: методы класса String, сборка строки в StringBuilder, форматирование через String.format() и printf(), регулярные выражения с Pattern и Matcher. Задачи сгруппированы по темам модуля; к большинству есть решение на Patreon, к части — видеоразбор.
Практика методов класса String
- Напишите метод, который принимает в качестве параметра любую строку, например “I like Java!!!”.
- Распечатать последний символ строки. Используем метод String.charAt().
- Проверить, заканчивается ли ваша строка подстрокой “!!!”. Используем метод String.endsWith().
- Проверить, начинается ли ваша строка подстрокой “I like”. Используем метод String.startsWith().
- Проверить, содержит ли ваша строка подстроку “Java”. Используем метод String.contains().
- Найти позицию подстроки “Java” в строке “I like Java!!!”.
- Заменить все латинские символы
aнаo. - Преобразуйте строку к верхнему регистру.
- Преобразуйте строку к нижнему регистру.
Неочевидный момент
В строке "I like Java!!!" буква a латинская. Если набрать её в русской раскладке, replace("а", "о") не найдёт ни одного совпадения и вернёт строку без изменений — ошибки при этом не будет.
Video walkthrough →Solution on Patreon →
Составляем строку с помощью класса StringBuilder
- Даны два числа, например 3 и 56. Составьте с помощью метода StringBuilder.append() строки:
3 + 56 = 59 3 - 56 = -53 3 * 56 = 168 - Замените символ “=” на слово “равно” (например,
3 + 56 равно 59). Используйте метод StringBuilder.replace().
Подсказка
StringBuilder.replace(start, end, str) принимает индексы, а не заменяемый символ. Позицию знака найдите через indexOf("="): sb.replace(i, i + 1, "равно").
Video walkthrough →Solution on Patreon →
Заменить каждое второе вхождение строки
Напишите метод, заменяющий в строке каждое второе вхождение «object-oriented programming» (без учёта регистра символов) на «OOP». Например, строка
Object-oriented programming is a programming language model organized around objects rather than "actions" and data rather than logic. Object-oriented programming blabla. Object-oriented programming bla. должна быть преобразована в
Object-oriented programming is a programming language model organized around objects rather than "actions" and data rather than logic. OOP blabla. Object-oriented programming bla.Как подойти к задаче
Ищите вхождения в цикле через indexOf(фраза, from) по копии строки в нижнем регистре и ведите счётчик: заменяйте только вхождения с чётным номером (2-е, 4-е и т.д.). Результат удобно собирать в StringBuilder, копируя куски исходной строки между найденными позициями.
Найти два средних знака строки
Дана строка чётной длины. Верните два её средних символа. Например:
"string"→"ri""code"→"od""Practice"→"ct"
Подсказка
Для строки длины n средние символы стоят на индексах n / 2 - 1 и n / 2, поэтому хватит одного вызова s.substring(n / 2 - 1, n / 2 + 1) — символ на позиции второго аргумента в результат не входит.
Список студентов
Создайте строку, используя форматирование: Студент [фамилия] получил [оценка] по [предмету]. Форматирование и вывод строки на консоль напишите в отдельном методе, который принимает фамилию, оценку и название предмета в качестве параметров. Выделите под фамилию 15 символов, под оценку 3 символа, под предмет – 10.
Пример вывода:
Студент Иванов получил 5 по Математике
Студент Петрова получил 4 по Физике
Студент Сидорова получил 3 по ПрограммированиюНюанс форматирования
Ширина в %-15s — минимальная: длинное значение не обрезается. «Программированию» — 16 символов, и при %-10s оно выйдет за пределы колонки целиком. Чтобы обрезать до 10 символов, добавьте точность: %-10.10s.
Video walkthrough →Solution on Patreon →
Отчёт о зарплате сотрудников с форматированием
Отчёт о сотрудниках · part 1 of 4 · part 2 →
- Создайте класс
Employeeс полямиfullnameиsalary. - Создайте массив, содержащий несколько объектов этого типа.
- Создайте класс
Reportсо статическим методомgenerateReport(Employee[] employees), который выводит информацию о зарплате всех сотрудников. - Используйте форматирование строк: пусть
salaryбудет выровнено по правому краю и выводится с 2 знаками после запятой. Можете добавить что-нибудь своё.
Подсказка
Флаг - выравнивает значение по левому краю, без него — по правому: %-20s%10.2f%n выведет имя в колонке шириной 20, а зарплату — справа в колонке шириной 10 с двумя знаками после запятой.
Простейшее регулярное выражение
Изменить регулярное выражение в примере для нахождения строк cab, ccab, cccab.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo2 {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("a*b");
Matcher matcher = pattern.matcher("aaab");
boolean b = matcher.matches();
System.out.println(b);
}
} Для строк cab, ccab, cccab программа должна выводить true, для ab — false.
Подсказка
Квантификатор * означает «ноль или более», + — «один или более». С c* шаблон пропустит и строку ab, в которой нет ни одной c.
Video walkthrough →Solution on Patreon →
Регулярное выражение, описывающее ссылку
Изменить регулярное выражение в примере – пусть reference1.org тоже считается ссылкой.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo3 {
public static void main(String[] args) {
System.out.println(test("google.com"));
System.out.println(test("reference1.ua"));
System.out.println(test("reference1.org"));
}
public static boolean test(String testString) {
Pattern pattern = Pattern.compile(".+\\.(com|ua|ru)");
Matcher matcher = pattern.matcher(testString);
return matcher.matches();
}
} Сейчас программа выводит true, true, false. Ожидаемый вывод после изменения:
true
true
trueГде искать
Допустимые домены перечислены в группе альтернатив в круглых скобках, разделённых символом |. Метод matches() возвращает true, только если строка заканчивается одним из них.
Video walkthrough →Solution on Patreon →
Регулярное выражение для нахождения Java X
Дана строка:
String text = "Versions: Java 5, Java 6, Java 7, Java 8, Java 12."; Найдите все подстроки вида «Java X», где X — номер версии, и распечатайте их. Между словом Java и номером может быть несколько пробелов.
Ожидаемый вывод:
Java 5
Java 6
Java 7
Java 8
Java 12Подсказка
Подойдёт шаблон "Java\\s+\\d+": \s+ — один или несколько пробельных символов, \d+ — одна или несколько цифр (с одиночным \d от Java 12 останется Java 1). Перебирайте совпадения циклом while (matcher.find()) и печатайте matcher.group().
Слово с минимальным числом символов
Найти слово, в котором число различных символов минимально. Слово может содержать буквы и цифры. Если таких слов несколько, найти первое из них. Например, в строке "fffff ab f 1234 jkjk" найденное слово должно быть "fffff".
Как посчитать различные символы
Без коллекций это можно сделать так: символ на позиции i встречается впервые, если word.indexOf(word.charAt(i)) == i. Число таких позиций — количество различных символов. Чтобы при равенстве осталось первое слово, обновляйте минимум только при строгом <.
Найти количество слов
Предложение состоит из нескольких слов, разделённых пробелами, например: "One two three раз два три one1 two2 123 ". Найдите количество слов, содержащих только символы латинского алфавита.
Ожидаемый результат для примера: 3.
Обратите внимание
Слово one1 не подходит: в нём есть цифра. Проверить слово целиком удобно через word.matches("[a-zA-Z]+") — matches() требует, чтобы под шаблон подошла вся строка.
Найти палиндром
Предложение состоит из нескольких слов, например: "Если есть хвосты по дз, начните с 1 несданного задания. 123 324 111 4554". Среди слов, состоящих только из цифр, найдите и выведите все слова-палиндромы — те, что одинаково читаются слева направо и справа налево.
Ожидаемый результат для примера: 1, 111, 4554.
Подсказка
Слово из цифр проверяется через word.matches("\\d+"), а палиндром — сравнением с перевёрнутой копией: new StringBuilder(word).reverse().toString().equals(word). Однозначное число — тоже палиндром.
Чек о покупке с форматированием
Интернет-магазин · part 3 of 11 · ← part 2 · part 4 →
При покупке выведите на консоль отчёт о купленных продуктах. Используйте форматирование. Например:
Продукты Цена
--------------------
Джинсы 1500,78
Юбка 1000,56
Галстук 500,78
--------------------
Итого: 3002,12Как выровнять колонки
Задайте одинаковую ширину шапке и строкам: "%-10s%10s%n" для заголовка и "%-10s%10.2f%n" для товаров. Сумму «Итого» считайте в цикле по купленным товарам, а не вписывайте вручную — так программа сама проверит арифметику.
Что повторить перед решением
Каждая задача закрепляет конкретный урок модуля «Строки в Java». Если задача не идёт, откройте урок из левой колонки таблицы — нужный метод разобран там с примером.
| Урок | Что понадобится | Задачи на этой странице |
|---|---|---|
| Класс String и его методы | charAt(), indexOf(), substring(), replace(), split() | Практика методов класса String, Два средних знака строки, Каждое второе вхождение, Слово с минимальным числом символов |
| StringBuffer и StringBuilder | append(), replace(), reverse() | Составляем строку с помощью StringBuilder, Найти палиндром |
| Форматирование строк | Ширина, точность и флаг выравнивания: %-15s, %10.2f | Список студентов, Отчёт о зарплате сотрудников, Чек о покупке |
| Регулярные выражения | Квантификаторы + и *, группы (a|b), matches() и find() | Простейшее регулярное выражение, Выражение для ссылки, Поиск Java X, Количество слов |
На чём чаще всего ошибаются
Большинство неверных решений в задачах на строки дают не сложные алгоритмы, а пять типичных промахов: сравнение через ==, выход за последний индекс, matches() вместо find(), неэкранированная точка в регулярном выражении и неожиданная запятая в отформатированном числе.
| Что пишут | Что происходит | Как правильно |
|---|---|---|
s1 == s2 | false для строки из new String("Java") или scanner.nextLine(), хотя текст тот же | s1.equals(s2), без учёта регистра — equalsIgnoreCase() (разбор в уроке) |
s.charAt(s.length()) | StringIndexOutOfBoundsException: последний индекс равен length() - 1 | s.charAt(s.length() - 1) |
matcher.matches() для поиска подстрок | false, если шаблон не покрывает всю строку целиком | Цикл while (matcher.find()) и matcher.group() |
Pattern.compile(".+.(com|org)") | Точка без экранирования означает любой символ: "googlexcom" тоже пройдёт проверку | ".+\\.(com|org)" — в Java-строке обратный слеш удваивается |
String.format("%.2f", 1500.78) | В русской локали по умолчанию получится 1500,78 — с запятой | String.format(Locale.US, "%.2f", x) даёт 1500.78 |
Перед отправкой решения
Сверьте вывод программы с примером из условия и пройдитесь по рекомендациям по оформлению кода: понятные имена переменных, отдельные методы вместо одного длинного main(), отсутствие «магических» чисел.
Часто задаваемые вопросы
С какой задачи начать, если строки только изучаете?
С «Практики методов класса String» и «Двух средних знаков строки», затем — StringBuilder и задачи на форматирование. Регулярные выражения оставьте напоследок, а задачи про слова и палиндромы решайте в конце: в них сочетаются сразу несколько тем.
Как посчитать количество слов в строке Java?
Обрежьте пробелы по краям через trim() и разбейте строку: text.trim().split("\\s+"). Без trim() строка " a b" даст массив ["", "a", "b"] с пустым первым элементом, а пустая строка "" даёт массив длины 1, а не 0 — этот случай проверяйте отдельно через isEmpty().
Можно ли в задаче про StringBuilder склеить строку через плюс?
Результат будет тем же, но задача тренирует именно append() и replace(). В цикле разница существенна: оператор + на каждой итерации создаёт новый объект String. Подробнее — в разделе Отличие между String, StringBuilder, StringBuffer.
Как проверить решение, если к задаче нет разбора на Patreon?
Сравните вывод с примером из условия, затем подайте граничные данные: пустую строку, строку из одного символа, строку из одних пробелов. Например, в задаче о двух средних символах "".substring(-1, 1) выбросит StringIndexOutOfBoundsException — решите заранее, что метод должен вернуть в этом случае.
Как искать подстроку без учёта регистра?
Через Pattern.compile(word, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE): без второго флага регистр игнорируется только для латиницы. Приём «привести обе строки к toLowerCase() и искать indexOf()» работает для латиницы и кириллицы, но для отдельных символов Unicode длина строки меняется: "İ".toLowerCase() возвращает два символа, и индексы в исходной строке съезжают.
Comments