Реалізація рядків у Java представлена трьома основними класами: String, StringBuffer та StringBuilder. У цьому записі буде розглянуто клас String.

Зміст:

  1. Створення об’єкта String
  2. Порівняння рядків
  3. Довжина рядка
  4. Конкатенація
  5. Форматування рядків у Java
  6. Перетворення рядків
  7. Метод join
  8. Інші корисні методи класу String у Java

Рядок – це об’єкт, котрий представляє послідовність символів. Для створення та маніпулювання рядками Java надає загальнодоступний final клас java.lang.String. Об’єкт класу String є immutable – після створення він не може бути змінений. Може скластись враження, що методи класу можуть змінювати цей об’єкт, але це невірно. Методи можуть тільки створювати і повертати нові рядки, в яких зберігається результат операції.

Створення об’єкта String

Об’єкт класу String можна створити кількома способами.

Використовуючи рядкові літерали:

String text = "Hello, World!";

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

Створення об’єкта String за допомогою конструктора:

String text = new String("Hello, World!");

Зберігання екземпляра класу String в пам’яті має деякі особливості:

  • Рядок створений за допомогою конструктора зберігається безпосередньо в heap (купа).
  • Рядок створений як рядковий літерал, зберігається в спеціальному місці купи – в пулі рядків (String pool).
  • При цьому, у пулі рядків зберігаються виключно унікальні значення рядкових літералів.
  • Коли ми оголошуємо змінну типу String і присвоюємо їй рядковий літерал, JVM звертається до пулу рядків і шукає там ідентичне значення. Якщо пул містить необхідне значення, то повертається посилання на відповідну адресу рядка, без виділення додаткової пам’яті. Якщо значення не знайдено, то новий рядок буде додано до пулу рядків, а посилання на нього присвоєно змінній.
  • Коли ми створюємо екземпляр класу String за допомогою оператора new (тобто конструктора класу), компілятор розміщує рядок в heap. При цьому, кожен рядок створений таким чином, поміщається в heap (і має своє посилання), навіть якщо таке значення вже існує у купі або пулі рядків.

Якщо в копії рядка немає явної потреби, використання конструкторів небажане і в них немає необхідності, оскільки рядки є незмінними. Постійне створення нових об’єктів у такий спосіб може призвести до зниження продуктивності. В таких випадках краще використовувати ініціалізацію за допомогою рядкових літералів. Незважаючи на це, розглянемо ще деякі конструктори для створення об’єктів String.

Створення String з масиву символів:

char[] chars = {'H', 'e', 'l', 'l', 'o'};
String text = new String(chars);

System.out.println(text); // Hello

Можна також створити об’єкт String з масиву байтів, додатково передавши параметр типу Charset, котрий буде відповідати за кодування (якщо не вказано – використовується Charset.defaultCharset(), який залежить від кодування операційної системи):

byte[] bytes = {72, 101, 108, 108, 111};
String text = new String(bytes);

System.out.println(text); // Hello

На завершення, конструктори котрі використовують об’єкти класів StringBuffer або StringBuilder, для створення об’єкта String:

// StringBuffer
StringBuffer stringBuffer = new StringBuffer("Hello");
stringBuffer.append(" ");
stringBuffer.append("World!");

String stringFromStringBuffer = new String(stringBuffer);
System.out.println(stringFromStringBuffer); // Hello World!

// StringBuilder
StringBuilder stringBuilder = new StringBuilder("Hello");
stringBuilder.append(" ");
stringBuilder.append("World!");

String stringFromStringBuilder = new String(stringBuilder);
System.out.println(stringFromStringBuilder); // Hello World!

Класи StringBuffer та StringBuilder докладніше будуть розглянуті в окремих записах.

Порівняння рядків

У Java порівняння рядків можна здійснювати кількома способами, в залежності від того, що саме потрібно перевірити.

1. Оператор == перевіряє, чи вказують дві змінні на один і той самий об’єкт String у пам’яті. Використовується лише для порівняння посилань, а не змісту рядків:

String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2); // true

Але якщо рядок створено через new, результат буде іншим:

String s3 = new String("Hello");
System.out.println(s1 == s3); // false

2. Метод equals() порівнює вміст рядків, незалежно від їх місцезнаходження у пам’яті:

String s3 = new String("Hello");        
System.out.println(s1.equals(s3)); // true

3. Метод equalsIgnoreCase() порівнює рядки ігноруючи регістр символів:

System.out.println("hello".equalsIgnoreCase("Hello")); // true

4. Метод compareTo() використовується для лексикографічного порівняння рядків, та повертає:

  • позитивне значення – якщо об’єкт котрий викликає, більший за об’єкт переданий як параметр
  • від’ємне значення – якщо об’єкт котрий викликає, менший за об’єкт переданий як параметр
  • нуль – якщо об’єкти рівні
System.out.println("apple".compareTo("banana")); // -1

Довжина рядка

Важливим атрибутом кожного рядка є його довжина. Дізнатись її можна за допомогою методу length(), який повертає кількість символів у рядку:

String text = "Java";
System.out.println(text.length()); // 4

Конкатенація

Конкатенація – це операція об’єднання рядків, котра повертає новий рядок, який є результатом об’єднання. Операція конкатенації для об’єктів String може бути виконана двома способами:

1. Метод concat():

String str1 = "Hello";
String str2 = " ";
String str3 = "World";
String result = str1.concat(str2).concat(str3);

System.out.println(result); // Hello World

Так як concat() повертає новий об’єкт String, можна створювати так звані “ланцюжки” викликів.

2. Перевантажені оператори + та +=:

String part1 = "Java";
String part2 = " Programming";

System.out.println(part1 + part2); // Java Programming


String message = "Hello";
message += " World";

System.out.println(message); // Hello World

Форматування рядків у Java

Клас String надає можливість форматування рядків. За це відповідає статичний метод format():

String name = "Anna";
int age = 25;

String info = String.format("Name %s, age %d years.", name, age);
System.out.println(info); // Name Anna, age 25 years.

Перетворення рядків

1. Перетворення числа у рядок:

int number = 42;
String strNumber = String.valueOf(number);

System.out.println(strNumber); // 42

2. Перетворення рядка у число:

String str = "123";
int num = Integer.parseInt(str);

System.out.println(num); // 123

3. Перетворення рядка у масив символів:

String text = "Hello";
char[] charArray = text.toCharArray();

System.out.println(Arrays.toString(charArray)); // [H, e, l, l, o]

Метод join

Статичний метод join(), надає зручний спосіб об’єднання кількох рядків в один, використовуючи заданий роздільник:

String[] languages = {"Java", "Python", "C++"};

String joined = String.join(" | ", languages);
System.out.println(joined);
// Java | Python | C++

Інші корисні методи класу String у Java

1. Перевірка чи рядок порожній – методи isEmpty() та isBlank() (доступно з Java 11):

String emptyStr = "";
String spaceStr = "  ";

System.out.println(emptyStr.isEmpty()); // true
System.out.println(spaceStr.isBlank()); // true

2. Отримання підрядка – метод substring():

String text = "Hello, World!";

String sub1 = text.substring(7);
System.out.println(sub1); // World!

String sub2 = text.substring(0, 5);
System.out.println(sub2); // Hello

3. Перевірка чи містить рядок вказаний підрядок – метод contains():

String text = "Java programming";

boolean containsJava = text.contains("Java");
System.out.println(containsJava); // true

4. Пошук першого/останнього входження підрядка у рядок – методи indexOf() та lastIndexOf():

String text1 = "Java programming";

int index = text1.indexOf("prog");
System.out.println(index); // 5


String text2 = "banana";

int lastIndex = text2.lastIndexOf("na");
System.out.println(lastIndex); // 4

5. Перевірка, чи починається/закінчується рядок вказаним підрядком – методи startsWith() та endsWith():

String filename = "document.pdf";

boolean startsWithDoc = filename.startsWith("doc");
System.out.println(startsWithDoc); // true

boolean isPDF = filename.endsWith(".pdf");
System.out.println(isPDF); // true

6. Розбиття рядка на підрядки – метод split():

String data = "apple,banana,orange";
String[] fruits = data.split(",");

for (String fruit : fruits) {
    System.out.println(fruit);
}
// apple
// banana
// orange

7. Заміна підрядка – методи replace() та replaceAll():

String text = "I love Java";
String replaced = text.replace("Java", "Python");
System.out.println(replaced); // I love Python

String numbers = "123-456-789";
String formatted = numbers.replaceAll("-", ".");
System.out.println(formatted); // 123.456.789

8. Видалення пробілів з початку та кінця рядка – метод trim():

String text = "  Hello World!  ";

String trimmed = text.trim();
System.out.println(trimmed); // "Hello World!"

9. Отримання символу за індексом – метод charAt():

String text = "Java";

char ch = text.charAt(1);
System.out.println(ch); // 'a'

10. Зміна регістру символів у рядку – методи toUpperCase() та toLowerCase():

String text = "Hello, World!";

String upper = text.toUpperCase();
System.out.println(upper); // HELLO, WORLD!

String lower = text.toLowerCase();
System.out.println(lower); // hello, world!


Мітки: