JavaRush /Курсы /JAVA 25 SELF /Преобразование коллекций

Преобразование коллекций

JAVA 25 SELF
28 уровень , 1 лекция
Открыта

1. Преобразование элементов коллекций

В программировании одна из самых частых операций — преобразование коллекции: у нас есть коллекция данных одного типа, и на её основе нужно создать новую коллекцию другого типа. Например, из списка объектов типа User получить список их имён (String), или из списка чисел — список их квадратов.

Самый фундаментальный и понятный способ в Java — использовать императивный подход, то есть обычный цикл for (часто — for-each).

Пример: из списка строк получить список их длин

Предположим, у нас есть список названий городов:

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

Наша задача — создать новый список, который будет содержать длину каждого названия. Итоговый результат должен быть: [6, 6, 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, 6, 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: неэффективное использование ресурсов. Для очень больших коллекций постоянное создание новых списков и копирование элементов может быть ощутимым по памяти и времени. В большинстве повседневных задач это приемлемо, но при обработке больших объёмов данных учитывайте сложность и, при необходимости, оптимизируйте подход.

1
Задача
JAVA 25 SELF, 28 уровень, 1 лекция
Недоступна
Формирование списка студентов для выпускного альбома 🎓
Формирование списка студентов для выпускного альбома 🎓
1
Задача
JAVA 25 SELF, 28 уровень, 1 лекция
Недоступна
Объединение сокровищ из разных сундуков 💰
Объединение сокровищ из разных сундуков 💰
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ