JavaRush /Java блог /Random UA /Метод split у Java: ділимо рядок на частини

Метод split у Java: ділимо рядок на частини

Стаття з групи Random UA
Давай поговоримо про метод String split : що він робить і навіщо потрібний. Неважко здогадатися, що він ділить рядок, але як це працює на практиці? Давай докладно розглянемо роботу методу та обговоримо деякі неочевидні деталі, а заразом дізнаємося, скільки методів split є в класі String насправді. Погнали!

Визначення та сигнатура для Java String.split

Метод split Java розділяє рядок на підрядки, використовуючи роздільник, який визначається за допомогою регулярного виразу. Наведемо сигнатуру методу та почнемо наше занурення:
String[] split(String regex)
З сигнатури зрозумілі дві речі:
  1. Метод повертає масив рядків.
  2. Метод приймає рядок regex як параметр.
Розберемо кожну річ окремо у розрізі визначення, наведеного вище.
  1. Метод повертає масив рядків.

    У визначенні є такі слова: "Метод split Java розділяє рядок на підрядки". Дані підрядки збираються методом масив і є його повертається значення.

  2. Метод приймає рядок regex як параметр.

    Знову ж таки, згадаємо визначення: "поділяє рядок на підрядки, використовуючи роздільник, який визначається за допомогою регулярного виразу". Regex, що приймається, - це шаблон регулярного виразу, який застосовується до вихідного рядка і за збігами визначає в ньому символ (або комбінацію символів) роздільника.

Метод split у Java: ділимо рядок на частини - 1

Split на практиці

Тепер ближчий до справи. Припустимо, що у нас є рядок зі словами. Наприклад, така:
I love Java
Нам потрібно розбити рядок на слова. Ми бачимо, що в даному рядку слова розділені один від одного пробілами. Пробіл - ідеальний кандидат на роль роздільника в даному випадку. Так виглядає код розв'язання цієї задачі:
public class Main {
    public static void main(String[] args) {
        String str = "I love Java";
        String[] words = str.split(" ");
        for (String word : words) {
            System.out.println(word);
        }
    }
}
Виведенням методу main будуть наступні рядки:
I love Java
Подивимося ще кілька прикладів того, як би відпрацював метод split :
Рядок Розділювач Результат роботи методу
"I love Java" " " (символ пропуску) { "I" , "love" , "Java" }
"192.168.0.1:8080" ":" { "192.168.0.1" , "8080" }
"Червоний, помаранчевий, жовтий" "," { "Червоний" , "помаранчевий" , "жовтий" }
"Червоний, помаранчевий, жовтий" "," { "Червоний" , "помаранчевий" , "жовтий" }
Зверніть увагу на різницю між останніми двома рядками в таблиці вище. У передостанньому рядку роздільником виступає символ комою, тому рядок розбився в такий спосіб, що у деяких словах є провідні прогалини. В останньому рядку як роздільник ми використовували символ коми і символ пробілу. Тому в результуючому масиві не було рядків з провідними пробілами. Це просто маленька деталь, де демонструється, як важливо уважно підбирати правильний роздільник.

Провідний роздільник

Є ще один важливий аспект. Якщо вихідний рядок починається з роздільника, першим елементом результуючого масиву буде порожній рядок. На прикладі це буде виглядати так: Вихідний рядок: " I love Java" Розділювач: " " Результуючий масив: { "" , "I" , "love" , "Java" } Але якщо вихідний рядок закінчується роздільником, а не починається, результат буде іншим: Вихідний рядок: "I love Java" Розділювач: "" Результуючий масив: { "I" , "love" , "Java"із символом роздільника в кінці та/або початку вихідного рядка:
public class Main {
    public static void main(String[] args) {
        print("I love Java".split(" "));
        print(" I love Java".split(" "));
        print("I love Java ".split(" "));
        print(" I love Java ".split(" "));
    }

    static void print(String[] arr) {
        System.out.println(Arrays.toString(arr));
    }
}
Висновок методу main буде таким:
[I, love, Java] [, I, love, Java] [I, love, Java] [, I, love, Java]
Ще раз зверніть увагу: коли у вихідному рядку перший символ – це символ роздільника, у результаті в масиві першим елементом буде порожній рядок.

Перевантажений побратим

У класі String є ще один метод split із такою сигнатурою:
String[] split(String regex, int limit)
Цей метод має додатковий параметр limit : він визначає, скільки разів шаблон regex буде застосовуватися до вихідного рядка. Нижче пояснення:

limit > 0

Застосовується ліміт -1 раз. При цьому довжина масиву не перевищуватиме значення limit . Останнім елементом масиву буде частина рядка, наступна за останнім знайденим роздільником. Приклад:
public class Main {
    public static void main(String[] args) {
        print("I love Java".split(" ", 1));
        print("I love Java".split(" ", 2));
        /*
         Висновок:
         [I love Java]
         [I, love Java]
        */
    }

    static void print(String[] arr) {
        System.out.println(Arrays.toString(arr));
    }
}

limit < 0

Шаблон для пошуку роздільника застосовується до рядка стільки разів, скільки можливо. Довжина підсумкового масиву може бути будь-якою. Приклад:
public class Main {
    public static void main(String[] args) {
        // Зверніть увагу на прогалину в кінці рядка
        print("I love Java ".split(" ", -1));
        print("I love Java ".split(" ", -2));
        print("I love Java ".split(" ", -12));
        /*
         Висновок:
        [I, love, Java, ]
        [I, love, Java, ]
        [I, love, Java, ]

        Зверніть увагу: останній елемент масиву -
        порожній рядок, що виник через прогалину
        в кінці вихідного рядка.
        */
    }

    static void print(String[] arr) {
        System.out.println(Arrays.toString(arr));
    }
}

limit 0

Як і у випадку з < 0, шаблон для пошуку роздільника застосовується до рядка стільки разів, скільки це можливо. Підсумковий масив може бути будь-якої довжини. Якщо останні елементи дорівнюють порожньому рядку, у підсумковому масиві вони будуть відкинуті. Приклад:
public class Main {
    public static void main(String[] args) {
        // Зверніть увагу на прогалину в кінці рядка
        print("I love Java ".split(" ", 0));
        print("I love Java ".split(" ", 0));
        print("I love Java ".split(" ", 0));
        /*
         Висновок:
        [I, love, Java]
        [I, love, Java]
        [I, love, Java]
        Зверніть увагу на відсутність порожніх рядків наприкінці масивів
        */
    }

    static void print(String[] arr) {
        System.out.println(Arrays.toString(arr));
    }
}
Якщо ми подивимося на реалізацію методу split з одним аргументом, побачимо, що даний метод викликає свого перевантаженого побратима з другим аргументом, що дорівнює нулю:
public String[] split(String regex) {
    return split(regex, 0);
}

Різні приклади

У робочій практиці іноді буває так, що ми маємо рядок, складений за певними правилами. Цей рядок може "приходити" в нашу програму звідки завгодно:
  • із стороннього сервісу;
  • із запиту до нашого сервера;
  • із конфігураційного файлу;
  • і т.д.
Зазвичай, у такій ситуації програмісту відомі "правила гри". Скажімо, програміст знає, що має інформацію про користувача, яка зберігається за таким шаблоном:
user_id|user_login|user_email
Наприклад візьмемо конкретні значення:
135|bender|bender@gmail.com
І ось перед програмістом стоїть завдання: написати метод, який надсилає електронний лист користувачеві. У його розпорядженні - інформація про користувача, записана у зазначеному вище форматі. Ну а підзавдання, яке ми продовжимо розбирати - вичленувати email-адресау із загальної інформації про користувача. Це один із прикладів, коли метод split може виявитися корисним. Адже якщо ми поглянемо на шаблон, ми зрозуміємо: щоб вичленувати email-адресау користувача з усієї інформації, нам потрібно лише розділити рядок за допомогою методу split. Тоді email-адресаа лежатиме в останньому елементі результуючого масиву. Наведемо приклад такого методу, який приймає рядок, що містить інформацію про користувача, і повертає email користувача. Для спрощення припустимо, що цей рядок завжди відповідає потрібному нам формату:
public class Main {
    public static void main(String[] args) {
        String userInfo = "135|bender|bender@gmail.com";
        System.out.println(getUserEmail(userInfo));
        // Висновок: bender@gmail.com
    }

    static String getUserEmail(String userInfo) {
        String[] data = userInfo.split("\\|");
        return data[2]; // або data[data.length - 1]
    }
}
Зверніть увагу на роздільник: "\\" . Так як у регулярних виразах "|" - це спеціальний символ, на якому пов'язана певна логіка, щоб використовувати його як звичайний (той, який ми хочемо знайти у вихідному рядку), потрібно екранувати цей символ за допомогою двох зворотних слішів. Розглянемо інший приклад. Допустимо, у нас є інформація про замовлення, яка записана приблизно в такому форматі:
item_number_1,item_name_1,item_price_1;item_number_2,item_name_2,item_price_2;...;item_number_n,item_name_n,item_price_n
Ну чи візьмемо конкретні значення:
1,огірки,20.05;2,помідори,123.45;3,зайці,0.50
Перед нами постає завдання: розрахувати підсумкову вартість замовлення. Тут нам доведеться використовувати метод split кілька разів. Першим кроком ми розділимо рядок через символ ";", на складові. Тоді в кожній такій частині ми матимемо інформацію про окремий товар, яку ми зможемо обробити надалі. А потім, у рамках кожного товару будемо розділяти інформацію за допомогою символу "," і брати з результуючого масиву елемент з певним індексом (у якому зберігається ціна), наводити її до числового вигляду та складати підсумкову вартість замовлення. Напишемо метод, який все це вважатиме:
public class Main {
    public static void main(String[] args) {
        String orderInfo = "1,огірки,20.05;2,помідори,123.45;3,зайці,0.50";
        System.out.println(getTotalOrderAmount(orderInfo));
        // Висновок: 144.0
    }

    static double getTotalOrderAmount(String orderInfo) {
        double totalAmount = 0d;
        final String[] items = orderInfo.split(";");

        for (String item : items) {
            final String[] itemInfo = item.split(",");
            totalAmount += Double.parseDouble(itemInfo[2]);
        }

        return totalAmount;
    }
}
Спробуй самостійно розібратися з тим, як працює цей метод. На основі даних прикладів можна сказати, що метод split використовується тоді, коли ми маємо деяку інформацію в рядковому вигляді, з якої нам необхідно вичленувати якусь більш специфічну інформацію.

Підсумки

Ми розглянули з тобою метод split класу String . Він потрібний для поділу рядка на складові за допомогою спеціального роздільника. Метод повертає масив рядків (складові частини рядка). Приймає регулярне вираз, за ​​яким знаходить символ(и) роздільника. Ми розглянули різні тонкощі роботи цього методу:
  • провідний символ роздільника;
  • перевантажений побратим із двома аргументами.
Також спробували змоделювати деякі ситуації "з життя", в яких використовували метод split для вирішення нехай і вигаданих, але цілком реалістичних проблем.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ