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
два ідентичних рядки, метод поверне однакові посилання. Цим можна користуватися для порівняння рядків за посиланнями. Приклад:
Код | Примітка |
---|---|
|
|
|
|
Навряд чи ви часто використовуватимете цей метод, проте про нього зазвичай запитують на співбесідах, тож його варто знати.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ