JavaRush /Курси /Java Syntax Zero /Додаткові класи для роботи з рядками в Java

Додаткові класи для роботи з рядками в Java

Java Syntax Zero
Рівень 10 , Лекція 6
Відкрита

1. Клас StringTokenizer

Є ще кілька сценаріїв, які дуже часто використовуються для роботи з рядками. Як розділити рядок на частини? Для цього є декілька способів.

Метод split()

Найпростіший спосіб розділити рядок на кілька частин — це скористатися методом split(). У нього потрібно передати як параметр регулярний вираз: спеціальний шаблон рядка-роздільника. Що таке регулярний вираз, ви дізнаєтеся у квесті Java Multithreading.

Приклад:

Код Результат
String str = "Good news everyone!";
String[] strings = str.split("ne");
System.out.println(Arrays.toString(strings));
Результатом буде масив із трьох рядків:
["Good ", "ws everyo", "!"]

Це простий спосіб, але часом такий підхід є надмірним. Якщо роздільників багато, наприклад «пробіл», «enter», «tab», «крапка», доводиться конструювати досить складний регулярний вираз. Його складно читати, отож у нього складно вносити зміни.

Клас StringTokenizer

У мові Java є спеціальний клас, призначений саме для розділення рядків на підрядки.

Цей клас не використовує регулярні вирази, натомість в нього просто передається рядок, який складається із символів-роздільників. Переваги цього підходу в тому, що рядок не відразу розбивається на шматочки, а поступово аналізується від початку до кінця.

Клас складається з конструктора і двох методів. У конструктор передається рядок, який потрібно розбити на частини, і рядок — набір символів, які використовуються як роздільники.

Методи Опис
String nextToken()
Повертає наступний підрядок
boolean hasMoreTokens()
Перевіряє, чи немає ще підрядків.

Цей клас трохи нагадує клас Scanner, який теж має методи nextLine() і hasNextLine().

Для створення об'єкта StringTokenizer використовують таку команду:

StringTokenizer ім'я = new StringTokenizer(рядок, роздільники);

де рядок — це рядок, який потрібно розділити на частини; а роздільники — це рядок, кожний символ в якому вважається символом-роздільником. Приклад:

Код Виведення на екран
String str = "Good news everyone!";

StringTokenizer tokenizer = new StringTokenizer(str,"ne");
while (tokenizer.hasMoreTokens())
{
   String token = tokenizer.nextToken();
   System.out.println(token);
}
Good 
ws 
v
ryo
!

Зауважте, що кожен символ у другому рядку, переданому в конструктор StringTokenizer, вважається роздільником.



2. Метод String.format() і клас StringFormatter

Клас String має ще один цікавий метод — format().

Припустімо, у вас є різні змінні з даними. Як вивести їх на екран одним рядком? Наприклад, маємо дані (лівий стовпець), які ми хочемо вивести на екран у певному вигляді (правий стовпець):

Код Виведення на екран
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;
User = {name: Amigo, age: 12 years, friend: Diego, weight: 200 kg.}

Ваш код матиме приблизно такий вигляд:

Код програми
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;

System.out.println("User = {name: " + name + ", age:" + age + " years, friend: " + friend+", weight: " + weight + " kg.}");

Такий код не дуже зручно читати. А якби імена змінних були довшими, код став би ще складнішим:

Код програми
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;

System.out.println("User = {name: " + user.getName() + ", age:" + user.getAge() + " years, friend: " + user.getFriends().get(0) + ", weight: " + user.getExtraInformation().getWeight() + " kg.}");

Не дуже зручно читати, чи не так?

Проте в реальних програмах така ситуація трапляється досить часто, тому я розповім, як спростити й скоротити цей код.

String.format

Клас String має статичний метод format(): він дає змогу визначити шаблон об'єднання рядка з даними. Загальний вигляд цієї команди такий:

String ім'я = String.format(шаблон, параметри);

Приклад:

Код Результат
String.format("Age=%d, Name=%s", age, name);
Age=12, Name=Amigo
String.format("Width=%d, Height=%d", width, height);
Width=20, Height=10
String.format("Fullname=%s", name);
Fullname=Diego

У метод format() першим параметром передається рядок-шаблон, який містить увесь потрібний текст, а в ті місця, куди потрібно вставити дані, вписано спеціальні символи типу %d, %s тощо.

Метод format() замінює ці символи %s і %d на параметри, вказані після рядка-шаблону. Коли потрібно підставити рядок, пишемо %s, а коли число — %d. Приклад:

Код Результат
String s = String.format("a=%d, b=%d, c=%d", 1, 4, 3);
s дорівнюватиме "a=1, b=4, c=3"

Скорочений перелік параметрів, які можна використовувати в шаблоні:

Символ Позначення
%s
String
%d
ціле число: byte, short, int, long
%f
дійсне число: float, double
%b
boolean
%c
char
%t
Date
%%
Символ %

Ці параметри вказують на тип даних, але є такі параметри, які вказують на порядок даних. Для того щоб вибрати параметр за номером (нумерація починається з одиниці), потрібно написати %1$d замість %d. Приклад:

Код Результат
String s = String.format("a=%3$d, b=%2$d, c=%d", 11, 12, 13);
s дорівнюватиме "a=13, b=12, c=11"

Замість %3$d підставиться 3-й параметр-змінна, замість %2$d — 2-й параметр-змінна, а замість %d — найперший параметр-змінна. Параметри шаблону %s, %d звертаються до параметрів-змінних незалежно від параметрів шаблону типу %3$d або %2$s.



3. String Pool

Усі рядки, що задано в коді як літерали, під час роботи програми зберігаються в пам'яті в особливому місці, яке має назву StringPool. StringPool — це спеціальний простір, створений для оптимізації зберігання рядків.

По-перше, рядки, визначені в коді, потрібно десь зберігати. Код — це команди, а дані (зокрема такі великі, як рядки) потрібно зберігати в пам'яті окремо від коду. У коді використовуються тільки посилання на об'єкти-рядки.

По-друге, можна усі однакові літерали зберегти в пам'яті лише один раз. Отак воно й працює. Коли код вашого класу завантажується Java-машиною, усі рядкові літерали додаються до StringPool (якщо їх там ще немає). Якщо такий рядок у StringPool вже є, просто використовується посилання на цей рядок.

Тому, якщо в коді присвоїти декільком змінним типу String однакові літерали, ці змінні будуть містити однакові посилання. У StringPool літерал додається тільки один раз, у решті випадків буде використовуватися посилання на рядок, уже завантажений у StringPool.

Отак це працює:

Код Робота зі StringPool
String a = "Привіт";
String b = "Привіт";
String c = "Бувай";
String[] pool = {"Привіт", "Бувай"};
a = pool[0];
b = pool[0];
c = pool[1];

Саме тому змінні a і b зберігатимуть однакові посилання.

Метод intern()

І найцікавіше: будь-який рядок можна програмним шляхом додати до StringPool. Для цього потрібно просто викликати для змінної типу String метод intern().

Метод intern() додасть рядок до StringPool, якщо його там ще немає, і поверне посилання на рядок зі StringPool.

Якщо за допомогою методу intern() додати до StringPool два ідентичних рядки, метод поверне однакові посилання. Цим можна користуватися для порівняння рядків за посиланнями. Приклад:

Код Примітка
String a = new String("Привіт");
String b = new String("Привіт");
System.out.println(a == b);


false
String a = new String("Привіт");
String b = new String("Привіт");

String t1 = a.intern();
String t2 = b.intern();
System.out.println(a == b);
System.out.println(t1 == t2);





false
true

Навряд чи ви часто використовуватимете цей метод, проте про нього зазвичай запитують на співбесідах, тож його варто знати.


Коментарі (22)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Vlad Рівень 21
25 вересня 2024
Працюємо💪
Ігор Рівень 41 Expert
18 травня 2023
я хочу заробляти як Амігоооо 😎
Гаркін Рівень 14
7 квітня 2024
Ну і як на 41 лвл, мрії здійснились? Або хоч наблизились до здійснення? Ps. Я також хочу заробляти стільки ж, скільки і Аміго у прикладі. Додам - при сьогодняшній вартості у.о.
Julia Рівень 22
11 лютого 2025
як успіх?)
Sanya Рівень 11 Expert
16 квітня 2023
Але, скажу я вам що таки в голові щось залишається.... Одне питання, як ви до ShortKey звикаєте?
Roma Chernesh Рівень 16
1 січня 2023
Навряд чи ви часто використовуватимете цей метод, проте про нього зазвичай запитують на співбесідах, тож його варто знати. >> судячи з розповідей моїх знайомих джунів - такими словами можна будь-яку тему з цього курсу описати:)
DmytroStepanenko Рівень 51
2 вересня 2022
не пробували написати в лекціях про countTokens(), щоб потім питати це в задачах...
dianosauric Рівень 42
16 вересня 2022
Таааак, тут не вистачило інформації про countTokens() і прикладу, щоб зрозуміти логіку як вирішувати задачу
TarasMkast Рівень 22
21 червня 2023
Оперативне використання гугла - одна із важливих функцій програміста ))
Ва Дим Рівень 28
1 квітня 2024
памятаю як перший раз проходив цю задачку то навіть не помітив підказки з цим методом )))
Serhii #2958832 Рівень 51 Expert
12 серпня 2022
В IntelliJ IDEA задача 0916 String.format() виводила "крякозябри". Після того, як змінив кодування (правий куток), а саме windows-1251 замість UTF-8 в консоль IntelliJ IDEA вивело нормальну кирилицю, але валідація через плагін не проходила. Довелось назад поставити UTF-8 і тоді задача нормально пройшла тестування. Думаю проблема в версіях JDK, бо перед цим переставляв jdk на версію 17.0.4. Тоді була інша проблема: при запуску java файлів на іншому пк через командну стрічку командами javac Main.java -> java Main, теж видавало набір символів, що не читаються. Методом декількох проб вирішилося так: File -> Project Structure -> Project -> Language level замість "13" поставив "17". Тепер UTF-8 номально виводиться і в командну стрічку IntelliJ IDEA і в WEB IDE і при валідації плагіном.
Dmitro Рівень 2
25 січня 2022
😎
Taras Woytowitch Рівень 16
8 січня 2022
Є хтось? Агов, люди, ви де?
HOLOS TYSHI Рівень 51
8 січня 2022
Я є. Бачив вже тебе в коментах)
kalkulator¹ Рівень 51
6 листопада 2022
хто ти воїн?
Kostiantyn Bogatyrchuk Рівень 14 Expert
15 лютого 2023
8 січня 2022, 09:53 - Рівень 16 Cхоже, що чувак закинув свої старання. що ж буде зі мною коли до 16 дійду?
Svitoij Рівень 23
27 березня 2023
Написано "Двірник"...
Kostiantyn Bogatyrchuk Рівень 14 Expert
27 березня 2023
ага. прибираю вулиці. хороша робота, на свіжому повітрі, начальство не парить мізки, правда страховки медицинської фірма не дає, тому і хочу у програмісти.
bogdan kravchuk Рівень 11
11 квітня 2023
ти теж закинув??
Kostiantyn Bogatyrchuk Рівень 14 Expert
6 травня 2023
скажімо так. брав вимушену відпустку)
vich3er Рівень 14
26 лютого 2024
і як зараз?
Julia Рівень 22
10 лютого 2025
експерт)