JavaRush /Курси /JAVA 25 SELF /Перетворення колекцій

Перетворення колекцій

JAVA 25 SELF
Рівень 28 , Лекція 1
Відкрита

1. Перетворення елементів колекцій

У програмуванні одна з найчастіших операцій — перетворення колекції: у нас є колекція даних одного типу, і на її основі потрібно створити нову колекцію іншого типу. Наприклад, зі списку обʼєктів типу User отримати список їхніх імен (String) або зі списку чисел — список їхніх квадратів.

Найпростіший і найзрозуміліший спосіб у Java — використовувати імперативний підхід, тобто звичайний цикл for (часто — for-each).

Приклад: зі списку рядків отримати список їхніх довжин

Припустімо, у нас є список назв міст:

List<String> cities = List.of("Лондон", "Париж", "Токіо", "Нью-Йорк");

Наше завдання — створити новий список, який міститиме довжину кожної назви. Підсумковий результат має бути: [6, 5, 5, 8].

Рішення за допомогою циклу for:

import java.util.ArrayList;
import java.util.List;

public class CollectionTransform {
    public static void main(String[] args) {
        List<String> cities = List.of("Лондон", "Париж", "Токіо", "Нью-Йорк");
        List<Integer> lengths = new ArrayList<>(); // Створюємо новий порожній список для результату

        for (String city : cities) {
            // Для кожного елемента списку cities обчислюємо його довжину...
            int length = city.length();
            // ...і додаємо цей результат до нового списку
            lengths.add(length);
        }

        System.out.println(lengths); // Виведе: [6, 5, 5, 8]
    }
}

Починаємо зі створення нової порожньої колекції для результатів — перетворення не змінює початкову колекцію. Для обходу початкової колекції використовуємо цикл for-each і всередині застосовуємо потрібну логіку (length()) до кожного елемента, а результат додаємо до нового списку через add.

2. Перетворення обʼєктів

Часто ми працюємо зі складнішими типами даних. Припустімо, у нас є клас Product, і потрібно отримати список його назв (або цін).

public class Product {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }
}

Тепер, маючи список продуктів, отримаємо список їхніх назв:

import java.util.ArrayList;
import java.util.List;

public class ProductExample {
    public static void main(String[] args) {
        List<Product> products = List.of(
            new Product("Ноутбук", 1200.0),
            new Product("Миша", 25.5),
            new Product("Клавіатура", 75.0)
        );

        // Створюємо новий список для назв
        List<String> productNames = new ArrayList<>();

        for (Product product : products) {
            // Для кожного обʼєкта Product отримуємо його назву
            productNames.add(product.getName());
        }

        System.out.println(productNames); // Виведе: [Ноутбук, Миша, Клавіатура]
    }
}

Логіка та сама: ітеруємося елементами початкової колекції, застосовуємо до кожного елемента потрібний метод (наприклад, getName()) і додаємо результат до нової колекції.

3. Робота з вкладеними колекціями

Розглянемо випадок зі списком списків: кілька відділів, у кожному — свій список працівників. Завдання — отримати один загальний («плоский») список усіх працівників.

Приклад: обʼєднання списків працівників

List<List<String>> departments = List.of(
    List.of("Ганна", "Борис"),
    List.of("Вікторія", "Гліб", "Дмитро"),
    List.of("Олена")
);

Хочемо отримати єдиний список: [Ганна, Борис, Вікторія, Гліб, Дмитро, Олена].

Спосіб 1: за допомогою методу addAll()

import java.util.ArrayList;
import java.util.List;

public class NestedCollectionExample {
    public static void main(String[] args) {
        List<List<String>> departments = List.of(
            List.of("Ганна", "Борис"),
            List.of("Вікторія", "Гліб", "Дмитро"),
            List.of("Олена")
        );

        List<String> allEmployees = new ArrayList<>();

        // Перебираємо кожен список (відділ)
        for (List<String> department : departments) {
            // Додаємо всі елементи з поточного списку до спільного списку
            allEmployees.addAll(department);
        }

        System.out.println(allEmployees); // [Ганна, Борис, Вікторія, Гліб, Дмитро, Олена]
    }
}

Спосіб 2: вкладений цикл — те саме, але «вручну»:

List<List<String>> departments = List.of(...);
List<String> allEmployees = new ArrayList<>();

for (List<String> department : departments) { // Зовнішній цикл за відділами
    for (String employee : department) {      // Внутрішній цикл за працівниками
        allEmployees.add(employee);
    }
}

System.out.println(allEmployees);

Обидва способи еквівалентні за результатом. Метод addAll() по суті інкапсулює логіку вкладеного циклу й робить код коротшим.

4. Складні випадки та перетворення з умовами

Іноді перетворення потрібно виконувати лише для елементів, які відповідають умові. Наприклад, отримати список назв міст, які починаються з літери «Н», і взяти їхні довжини. Тут ми поєднуємо фільтрацію та перетворення: if + виклик методу (length()).

import java.util.ArrayList;
import java.util.List;

public class ConditionalTransform {
    public static void main(String[] args) {
        List<String> cities = List.of("Лондон", "Париж", "Токіо", "Нью-Йорк", "Нюрнберг");
        List<Integer> lengths = new ArrayList<>();

        for (String city : cities) {
            // Спочатку перевіряємо умову
            if (city.startsWith("Н")) {
                // Якщо умову виконано, застосовуємо перетворення
                lengths.add(city.length());
            }
        }

        System.out.println(lengths); // Виведе: [8, 8]
    }
}

Шаблон такий: усередині циклу спершу фільтруємо елемент за умовою (startsWith, порівняння, перевірка діапазону тощо), потім застосовуємо потрібне перетворення й додаємо результат до нового списку.

5. Типові помилки та підводні камені

Помилка № 1: зміна початкової колекції під час обходу. Поширена помилка — спроба додавати/видаляти елементи з початкової колекції безпосередньо в циклі for-each. Це призводить до помилок і непередбачуваної поведінки. Рішення: завжди створюйте новий список для результатів і наповнюйте його.

Помилка № 2: некоректне приведення типів. Якщо ви працюєте з «сирими» колекціями (наприклад, через Object) і виконуєте перетворення елементів до неправильного типу, отримаєте ClassCastException. Використовуйте узагальнення (List<T>) і стежте за сигнатурами.

Помилка № 3: неефективне використання ресурсів. Для дуже великих колекцій постійне створення нових списків і копіювання елементів можуть бути відчутними за витратами памʼяті й часу. У більшості повсякденних завдань це прийнятно, але під час обробки великих обсягів даних враховуйте складність і, за потреби, оптимізуйте підхід.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ