Розуміння підрядка в Java: базовий посібник

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

Але перед тим, як ми заглибимося в цю тему, важливо зрозуміти основні концепції, пов’язані з підрядками.

Що таке рядки та підрядки?

У Java рядок — це послідовність символів. Кожен рядок в Java є об’єктом. Рядок може містити літери, цифри, спеціальні символи та навіть пробіли. Підрядок, у свою чергу, є частиною, або підмножиною, іншого рядка в Java.

Наприклад, “Geek” є підрядком рядка “techukraine.net”. Підрядки дають нам змогу витягувати конкретні фрагменти з рядків.

Якщо у вас є повне ім’я “Іван Петренко”, а вам потрібне лише ім’я “Іван”, ви можете легко отримати його, використовуючи підрядки. Крім того, маючи список імен “Іван, Петро, Марія” і бажаючи перевірити, чи є серед них “Іван”, ви також можете скористатися підрядками. Це лише прості приклади. Застосування підрядків є дуже різноманітним, і розуміння їхньої роботи відкриває багато можливостей.

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

#1. Використання методу ‘substring()’

Метод ‘substring()’ дозволяє створювати підрядки з великою легкістю. Він може приймати один або два параметри: `startIndex` або `startIndex` і `endIndex`, і повертає потрібний нам підрядок.

Залежно від того, скільки параметрів ми передаємо, є два способи його використання. Розглянемо їх докладніше.

substring(int startIndex)

Перший варіант — це використання методу у формі `substring(startIndex)`. Тут метод отримує ціле число в якості вхідного параметра, яке представляє початкову позицію підрядка. Він повертає підрядок, що починається з вказаного індексу і триває до кінця оригінального рядка.

Розглянемо наступний приклад:

public class Substrings{    
    public static void main(String args[]){    
    String str="techukraine.net";    
    System.out.println("Given String: " + str);  
    System.out.println("Substring: " +str.substring(4)); //індексація рядків починається з 0
    }  
   }

Результат:

Given String: techukraine.net
Substring: ukraine.net

У цьому прикладі, вихідний рядок “techukraine.net”, а отриманий підрядок — “ukraine.net”. Він починається з вказаного індексу 4, тобто з п’ятої позиції, та триває до кінця рядка.

substring(int startIndex, int endIndex)

Це ще один спосіб застосування методу `substring` класу String. Ми можемо передати два цілих числа в метод: початковий та кінцевий індекси. Щоб використовувати цей варіант, застосовуємо його у форматі `substring(startIndex, endIndex)`.

Для кращого розуміння розглянемо наступний приклад коду:

public class Substrings{    
    public static void main(String args[]){    
    String str="GeekFlareFans";    
    System.out.println("Given String: " + str);  
    System.out.println("Substring: " +str.substring(4,9));  //отримуємо підрядок з індекса 4 до індексу 8.

    }  
   }

Результат:

Given String: GeekFlareFans
Substring: Flare

Як бачимо, для рядка “GeekFlareFans” він виводить підрядок “Flare”. Ми вказали початковий індекс 4 та кінцевий індекс 9. Підрядок починається з елемента з індексом 4 і закінчується перед індексом 9. Важливо пам’ятати, що елемент з кінцевим індексом не включається. Таким чином, ми отримуємо підрядок, який містить елементи до кінцевого індексу, але виключає його.

#2. Використання методу split()

`split()` — це ще один метод класу String в Java, який допомагає нам створювати підрядки. Він корисний, коли декілька фрагментів інформації зберігаються в одному рядку із спільним роздільником.

Синтаксис цього методу використовує термін “регулярний вираз”, який може вас налякати. Давайте розберемося, що таке регулярний вираз перед тим, як рухатися далі. Regex — це скорочення від “regular expression” (регулярний вираз). Регулярний вираз — це послідовність символів, яка описує шаблон в рядку або тексті. В контексті методу `split` наш роздільник — це регулярний вираз.

Метод `split()` може приймати до двох параметрів: рядок регулярного виразу та ціле число-обмеження. Регулярний вираз — це роздільник, який, коли знаходиться, розділяє початковий рядок на дві частини: частину перед регулярним виразом і частину після нього.

Наприклад, уявімо, що ви намагаєтеся розділити рядок “abcdef” на “bcd” як регулярний вираз. В результаті отримаємо підрядки “a” та “ef”.

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

split(рядок регулярного виразу)

Перший метод отримує лише рядок регулярного виразу у форматі `split(regex)`. Він не має граничної змінної; тому повертає всі розділені підрядки у вигляді масиву.

Розглянемо приклад коду для кращого розуміння:

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare";
    String[] substrings=str.split("%");
    System.out.println("Given String: " + str);
    System.out.println("First Substring: " + substrings[0]);
    System.out.println("Second Substring: " + substrings[1]);
     
    }  
}

Результат:

Given String: Geek%Flare
First Substring: Geek
Second Substring: Flare

Як видно з коду, заданий рядок має роздільник-регулярний вираз “%”. Це не обов’язково один символ, це може бути будь-який рядок з будь-якою кількістю символів. Метод `split()` ігнорує цей регулярний вираз та повертає всі рядки, розділені ним. Підрядки зберігаються у масиві.

У наведеному прикладі рядком є “Geek%Flare”. Тому ми отримуємо масив з двома елементами: “Geek” і “Flare”. Ми звертаємося до них за відповідними індексами (0, 1) та виводимо “Geek” і “Flare” на консоль.

Також важливо зазначити, що якщо не передати жодних параметрів методу, це призведе до помилки. Але якщо ми передамо порожній рядок (“”) як регулярний вираз, ми отримаємо кожен окремий символ як підрядок. Розглянемо приклад для ілюстрації.

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare";
    String[] substrings=str.split("");
    System.out.println(Arrays.toString(substrings));
     
    }  
}

Результат:

[G, e, e, k, %, F, l, a, r, e]

З прикладу видно, що коли параметр регулярного виразу — це порожній рядок, метод повертає всі символи як окремі підрядки, що можна побачити, надрукувавши масив, повернутий методом `split()`.

split(рядок регулярного виразу, int обмеження)

Другий варіант цього методу дає нам більше контролю над вихідними даними та дозволяє додатково налаштувати результат. Метод `split()` приймає два параметри: регулярний вираз та параметр `limit` у форматі `split(regex, limit)`.

`limit` — це кількість кінцевих рядків, які виводяться. Залежно від значення ліміту є три варіанти:

Випадок 1: якщо `limit>0`, результуючий масив міститиме вихідні дані, але він застосує розділення не більше ніж (`limit`-1) разів. Масив не міститиме більше елементів, ніж вказано в `limit`, а всі рядки, які не були розділені, залишаться без змін. Розглянемо приклад для кращого розуміння.

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare%is%the%best";
    String[] substrings=str.split("%",2);
    System.out.println(Arrays.toString(substrings));
     
    }  
}

Результат:

[Geek, Flare%is%the%best]

Зверніть увагу, що в результуючому масиві є лише два елементи, що відповідає значенню параметра `limit`. Також, розділення застосувалося лише один раз, тобто (`limit` – 1) раз.

Проте, якщо регулярний вираз зустрічається два рази поспіль (“%%”), це призведе до появи порожніх підрядків. Розгляньте наступний приклад коду для кращого розуміння.

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare%is%%the%best%%%";
    String[] substrings=str.split("%",5);
    System.out.println(Arrays.toString(substrings));
     
    }  
}

Результат:

[Geek, Flare, is, , the%best%%%]

Загалом, якщо за “%” слідує інший “%” або кінець рядка, це створює порожній підрядок.

Випадок 2: якщо `limit<0`, розділення застосовується стільки разів, скільки можливо, без обмеження розміру масиву, але масив буде містити порожні підрядки, якщо регулярний вираз зустрічається два рази поспіль (“%%”).

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare%is%%the%best%%%";
    String[] substrings=str.split("%",-1);
    System.out.println(Arrays.toString(substrings));
     
    }  
}

Результат:

[Geek, Flare, is, , the, best, , , ]

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

Випадок 3: якщо `limit=0`, розділення також застосовується максимально можливу кількість разів, але всі порожні підрядки в кінці рядка відкидаються з масиву.

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare%is%%the%best%%%";
    String[] substrings=str.split("%",0);
    System.out.println(Arrays.toString(substrings));
     
    }  
}

Результат:

[Geek, Flare, is, , the, best]

Ми бачимо, що результати схожі для `limit=-1` та `limit=0`, але в кінці немає порожніх підрядків. Іншими словами, порожні підрядки в кінці масиву ігноруються.

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

Перевірка наявності підрядка в рядку

Крім створення підрядків з існуючих рядків, ми також можемо перевірити, чи існує певний підрядок всередині іншого рядка. Це швидкий та простий спосіб пошуку підрядка, і він корисний у багатьох ситуаціях. Але як це зробити? Існує декілька методів для цього. Розглянемо їх.

Використання методу ‘contains()’

Ми можемо дуже легко перевірити наявність підрядка за допомогою методу `contains()`. Цей метод класу String приймає рядок як вхідні дані, який представляє наш підрядок, та повертає логічне значення (true або false), яке вказує, чи є підрядок усередині рядка чи ні. Цей метод можна використовувати всередині блоків `if-else`, унарних операторів та інших місцях для реалізації складної логіки.

Давайте детальніше розглянемо цей метод.

public class Substrings{    
    public static void main(String args[]){    
    String str="techukraine.net";    
    System.out.println("Does it contain ukraine? \n"+ str.contains("ukraine"));  
    }  
}

Результат:

Does it contain ukraine? 
true

Код перевіряє рядок “techukraine.net” на наявність слова “ukraine” і, успішно знайшовши його, повертає логічне значення “true”, підтверджуючи наявність підрядка.

public class Substrings{    
    public static void main(String args[]){    
    String str="techukraine.net";    
    System.out.println("Does it contain Flare? \n"+ str.contains("Flare"));  
    }  
}

Результат:

Does it contain Flare? 
false

З прикладу видно, що якщо підрядок не знайдено в рядку, метод повертає “false”, вказуючи на його відсутність. Таким чином, ми можемо легко перевірити, чи існує підрядок.

Знаходження позиції підрядка

#1. Використання ‘indexOf()’

Метод `indexOf()` можна використовувати для пошуку підрядка, а також для знаходження його індексу. Метод приймає як вхідні дані рядок або символ і повертає позицію його першого входження. Але він може надати нам лише індекс першого входження, і не може підтвердити, чи існують інші входження. Також важливо пам’ятати: якщо підрядок не існує, метод повертає -1.

Давайте детальніше розглянемо цей метод.

public class Substrings{    
    public static void main(String args[]){    
    String str="GeekFlareGeekFlare";    
    System.out.println("Index of Flare: "+ str.indexOf("Flare"));  
    }  
}

Результат:

Index of Flare: 4

У цьому прикладі перше входження підрядка “Flare” починається з індексу 4 в рядку “GeekFlareGeekFlare”. Тому, як і очікувалося, функція повернула цей індекс.

#2. Використання ‘lastIndexOf()’

`lastIndexOf()` дуже схожий на `indexOf()`. Обидва методи приймають як вхідні дані підрядок і повертають індекс його позиції. Він навіть повертає те ж саме значення, коли не може знайти підрядок у вказаному рядку. Обидва методи повертають -1 у випадку невдалого пошуку.

Але тоді як `indexOf()` повертає індекс першого входження підрядка, `lastIndexOf()` повертає індекс останнього входження.

Розглянемо приклад коду:

public class Substrings{    
    public static void main(String args[]){    
    String str="GeekFlareGeekFlare";    
    System.out.println("Last index of Flare: "+ str.lastIndexOf("Flare"));  
    }  
}

Результат:

Last index of Flare: 13

З цього результату ми бачимо, що метод `lastIndexOf()` працює, як очікувалося, і ми отримуємо індекс останнього входження підрядка “Flare” в рядку “GeekFlareGeekFlare”.

Часті питання

Як використовувати метод `split()` для створення непорожніх підрядків?

Якщо є кілька екземплярів рядка регулярного виразу в основному рядку один за одним (“Hello%%Hi”, де регулярний вираз “%”), метод `split()` розглядає перший екземпляр як символ розриву, а решта дають порожній рядок. Щоб цього уникнути, ми можемо встановити параметр `limit` як 0. У такому випадку вихідні дані будуть містити тільки непорожні рядки.

Чи повертає `indexOf()` індекси всіх входжень підрядка?

Ні, `indexOf()` не повертає індекси всіх входжень підрядка. За допомогою `indexOf()` ми отримуємо ціле число, що містить індекс першого входження підрядка. Якщо метод не може знайти підрядок, він поверне -1.

Що повертає метод `substring()`, якщо дані індекси не існують у рядку?

Якщо заданий початковий або кінцевий індекси не існують в рядку, компілятор видасть помилку. Помилка буде містити “java.lang.StringIndexOutOfBoundsException:”, і програма не виконається.

Висновок

У цій статті ми обговорили різні методи та основи для роботи з підрядками. Ми навчилися створювати підрядки і перевіряти, чи існує підрядок у рядку. Це дасть вам глибше розуміння того, як працювати з підрядками. Застосовуйте приклади на практиці і продовжуйте тренуватися, щоб повністю освоїти підрядки.

Також рекомендуємо переглянути наш список запитань для співбесіди на Java.