1. Клас StringTokenizer
Є ще кілька сценаріїв, які дуже часто використовуються для роботи з рядками. Як розділити рядок на частини? Для цього є декілька способів.
Метод split()
Найпростіший спосіб розділити рядок на кілька частин — це скористатися методом split(). У нього потрібно передати як параметр регулярний вираз: спеціальний шаблон рядка-роздільника. Що таке регулярний вираз, ви дізнаєтеся у квесті Java Multithreading.
Приклад:
| Код | Результат |
|---|---|
|
Результатом буде масив із трьох рядків: |
Це простий спосіб, але часом такий підхід є надмірним. Якщо роздільників багато, наприклад «пробіл», «enter», «tab», «крапка», доводиться конструювати досить складний регулярний вираз. Його складно читати, отож у нього складно вносити зміни.
Клас StringTokenizer
У мові Java є спеціальний клас, призначений саме для розділення рядків на підрядки.
Цей клас не використовує регулярні вирази, натомість в нього просто передається рядок, який складається із символів-роздільників. Переваги цього підходу в тому, що рядок не відразу розбивається на шматочки, а поступово аналізується від початку до кінця.
Клас складається з конструктора і двох методів. У конструктор передається рядок, який потрібно розбити на частини, і рядок — набір символів, які використовуються як роздільники.
| Методи | Опис |
|---|---|
|
Повертає наступний підрядок |
|
Перевіряє, чи немає ще підрядків. |
Цей клас трохи нагадує клас Scanner, який теж має методи nextLine() і hasNextLine().
Для створення об'єкта StringTokenizer використовують таку команду:
StringTokenizer ім'я = new StringTokenizer(рядок, роздільники);
де рядок — це рядок, який потрібно розділити на частини; а роздільники — це рядок, кожний символ в якому вважається символом-роздільником. Приклад:
| Код | Виведення на екран |
|---|---|
|
|
Зауважте, що кожен символ у другому рядку, переданому в конструктор StringTokenizer, вважається роздільником.
2. Метод String.format() і клас StringFormatter
Клас String має ще один цікавий метод — format().
Припустімо, у вас є різні змінні з даними. Як вивести їх на екран одним рядком? Наприклад, маємо дані (лівий стовпець), які ми хочемо вивести на екран у певному вигляді (правий стовпець):
| Код | Виведення на екран |
|---|---|
|
|
Ваш код матиме приблизно такий вигляд:
| Код програми |
|---|
|
Такий код не дуже зручно читати. А якби імена змінних були довшими, код став би ще складнішим:
| Код програми |
|---|
|
Не дуже зручно читати, чи не так?
Проте в реальних програмах така ситуація трапляється досить часто, тому я розповім, як спростити й скоротити цей код.
String.format
Клас String має статичний метод format(): він дає змогу визначити шаблон об'єднання рядка з даними. Загальний вигляд цієї команди такий:
String ім'я = String.format(шаблон, параметри);
Приклад:
| Код | Результат |
|---|---|
|
|
|
|
|
|
У метод format() першим параметром передається рядок-шаблон, який містить увесь потрібний текст, а в ті місця, куди потрібно вставити дані, вписано спеціальні символи типу %d, %s тощо.
Метод format() замінює ці символи %s і %d на параметри, вказані після рядка-шаблону. Коли потрібно підставити рядок, пишемо %s, а коли число — %d. Приклад:
| Код | Результат |
|---|---|
|
s дорівнюватиме "a=1, b=4, c=3" |
Скорочений перелік параметрів, які можна використовувати в шаблоні:
| Символ | Позначення |
|---|---|
|
String |
|
ціле число: byte, short, int, long |
|
дійсне число: float, double |
|
boolean |
|
char |
|
Date |
|
Символ % |
Ці параметри вказують на тип даних, але є такі параметри, які вказують на порядок даних. Для того щоб вибрати параметр за номером (нумерація починається з одиниці), потрібно написати %1$d замість %d. Приклад:
| Код | Результат |
|---|---|
|
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 |
|---|---|
|
|
Саме тому змінні a і b зберігатимуть однакові посилання.
Метод intern()
І найцікавіше: будь-який рядок можна програмним шляхом додати до StringPool. Для цього потрібно просто викликати для змінної типу String метод intern().
Метод intern() додасть рядок до StringPool, якщо його там ще немає, і поверне посилання на рядок зі StringPool.
Якщо за допомогою методу intern() додати до StringPool два ідентичних рядки, метод поверне однакові посилання. Цим можна користуватися для порівняння рядків за посиланнями. Приклад:
| Код | Примітка |
|---|---|
|
|
|
|
Навряд чи ви часто використовуватимете цей метод, проте про нього зазвичай запитують на співбесідах, тож його варто знати.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ