Как объединить два списка в Java: 5 рабочих способов с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: зачем объединять списки в Java и как не запутаться

Представьте: у вас есть два списка задач — «срочные» и «важные». Или два списка клиентов — из базы за прошлый месяц и за текущий. Чтобы работать с ними как с единым целым, их нужно объединить. В Java эта задача встречается настолько часто, что вопрос «How do I join two lists in Java?» на Stack Overflow собирает тысячи просмотров. И это не случайно: у новичков объединение списков часто вызывает путаницу — то ошибка компиляции, то список оказывается неизменяемым, то теряются данные.

В этой статье мы разберём 5 проверенных способов объединить два списка в Java — от классического addAll до элегантного Stream API. Вы узнаете, какой метод выбрать для разных ситуаций, как избежать подводных камней и написать код, который будет работать быстро и предсказуемо. Поехали!

Способ 1: Классический addAll — просто и надёжно

Самый прямой путь — использовать метод addAll() из интерфейса Collection. Он добавляет все элементы одной коллекции в другую. Звучит идеально, но есть нюанс: он изменяет исходный список. Если вам нужно сохранить оригинальные списки нетронутыми — создавайте новый.

Пример: объединение с сохранением оригиналов

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

public class JoinListsExample {
    public static void main(String[] args) {
        List<String> listA = new ArrayList<>(List.of("Java", "Python", "C++"));
        List<String> listB = new ArrayList<>(List.of("JavaScript", "Go", "Rust"));

        // Создаём новый список и добавляем в него оба списка
        List<String> mergedList = new ArrayList<>(listA);
        mergedList.addAll(listB);

        System.out.println(mergedList); // [Java, Python, C++, JavaScript, Go, Rust]
        // Оригинальные списки не изменились
    }
}

Плюсы: интуитивно понятно, работает с любыми типами List, не требует Java 8+.

Минусы: изменяет исходный список, если не создать новый; не поддерживает ленивые вычисления.

Способ 2: Stream API — современный и гибкий

Если вы используете Java 8 или новее, Stream API предлагает элегантный способ объединения списков. Он не изменяет исходные данные и легко комбинируется с другими операциями — фильтрацией, сортировкой, трансформацией.

Базовое объединение через Stream.concat

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamJoinExample {
    public static void main(String[] args) {
        List<String> listA = List.of("Красный", "Зелёный", "Синий");
        List<String> listB = List.of("Жёлтый", "Фиолетовый");

        List<String> mergedList = Stream.concat(listA.stream(), listB.stream())
                                         .collect(Collectors.toList());

        System.out.println(mergedList); // [Красный, Зелёный, Синий, Жёлтый, Фиолетовый]
    }
}

Объединение с фильтрацией и сортировкой

Допустим, нужно объединить два списка чисел, оставить только чётные и отсортировать по убыванию:

import java.util.List;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamAdvancedJoin {
    public static void main(String[] args) {
        List<Integer> listA = List.of(5, 2, 8, 1);
        List<Integer> listB = List.of(7, 4, 9, 3);

        List<Integer> result = Stream.concat(listA.stream(), listB.stream())
                                       .filter(n -> n % 2 == 0)   // только чётные
                                       .sorted(Comparator.reverseOrder())
                                       .collect(Collectors.toList());

        System.out.println(result); // [8, 4, 2]
    }
}

Плюсы: функциональный стиль, ленивые вычисления, легко комбинировать с другими операциями.

Минусы: требует Java 8+, немного сложнее для новичков.

Способ 3: ListUtils из Apache Commons Collections

Если вы уже используете библиотеку Apache Commons Collections (а это популярное решение в enterprise-проектах), утилита ListUtils упрощает объединение до одной строки.

Для начала добавьте зависимость в pom.xml (Maven):

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

Пример использования

import org.apache.commons.collections4.ListUtils;
import java.util.List;

public class ApacheJoinExample {
    public static void main(String[] args) {
        List<String> listA = List.of("A", "B", "C");
        List<String> listB = List.of("D", "E");

        List<String> merged = ListUtils.union(listA, listB);

        System.out.println(merged); // [A, B, C, D, E]
    }
}

Важно: ListUtils.union возвращает новый список и не изменяет исходные.

Плюсы: краткий код, не нужно писать утилиты самому.

Минусы: добавляет зависимость в проект; метод union работает как addAll — не удаляет дубликаты.

Способ 4: Plain Java — создаём свой утилитный метод

Иногда хочется иметь под рукой собственный метод, который делает ровно то, что нужно. Например, объединять списки с удалением дубликатов или с проверкой на null. Напишем универсальный метод:

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

public class ListUtilsCustom {

    // Объединяет два списка, игнорируя null
    public static <T> List<T> safeJoin(List<T> list1, List<T> list2) {
        List<T> result = new ArrayList<>();
        if (list1 != null) result.addAll(list1);
        if (list2 != null) result.addAll(list2);
        return result;
    }

    // Объединяет два списка, удаляя дубликаты (порядок первого списка сохраняется)
    public static <T> List<T> joinUnique(List<T> list1, List<T> list2) {
        List<T> result = new ArrayList<>(list1);
        for (T item : list2) {
            if (!result.contains(item)) {
                result.add(item);
            }
        }
        return result;
    }

    public static void main(String[] args) {
        List<String> a = List.of("один", "два", "три");
        List<String> b = List.of("два", "четыре");

        System.out.println(safeJoin(a, b));    // [один, два, три, два, четыре]
        System.out.println(joinUnique(a, b));  // [один, два, три, четыре                

Блоги

Рекомендаций по книгам