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: неэффективное использование ресурсов. Для очень больших коллекций постоянное создание новых списков и копирование элементов может быть ощутимым по памяти и времени. В большинстве повседневных задач это приемлемо, но при обработке больших объёмов данных учитывайте сложность и, при необходимости, оптимизируйте подход.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ