← Назад к вопросам

Как создать копию коллекции?

2.2 Middle🔥 151 комментариев
#Коллекции#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Копирование коллекций в Java

В Java существует несколько способов создать копию коллекции, каждый из которых имеет свои особенности и уровень глубины копирования.

1. Поверхностное копирование (Shallow Copy)

а) Через конструктор коллекции

List<String> original = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> copy = new ArrayList<>(original);  // Копирует ссылки на элементы

copy.add("D");
System.out.println(original);  // [A, B, C]
System.out.println(copy);      // [A, B, C, D]

Это самый быстрый способ, создаёт новый список, но элементы остаются одни и те же (ссылки копируются).

б) Через addAll()

List<String> original = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> copy = new ArrayList<>();
copy.addAll(original);

в) Через ArrayList.clone()

ArrayList<String> original = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<String> copy = (ArrayList<String>) original.clone();

2. Копирование через Stream API (Java 8+)

List<String> original = new ArrayList<>(Arrays.asList("A", "B", "C"));

// Копирование в новый список
List<String> copy = original.stream()
    .collect(Collectors.toList());

// Неизменяемая копия
List<String> immutableCopy = original.stream()
    .collect(Collectors.toUnmodifiableList());

// Копирование в HashSet
Set<String> setCopy = original.stream()
    .collect(Collectors.toSet());

3. Копирование с помощью Collections.copy()

List<String> original = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> copy = new ArrayList<>(original.size());

// Заполняем копию nullами
for (int i = 0; i < original.size(); i++) {
    copy.add(null);
}

// Копируем элементы
Collections.copy(copy, original);

// Или просто
List<String> copy2 = new ArrayList<>(original);  // Проще

4. Глубокое копирование (Deep Copy) для объектов

Когда коллекция содержит сложные объекты, нужна глубокая копия:

а) Через Stream с map()

public class User {
    private String name;
    private int age;
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // Copy constructor
    public User(User other) {
        this.name = other.name;
        this.age = other.age;
    }
}

List<User> original = new ArrayList<>(Arrays.asList(
    new User("Alice", 25),
    new User("Bob", 30)
));

// Глубокое копирование
List<User> deepCopy = original.stream()
    .map(User::new)  // Используем copy constructor
    .collect(Collectors.toList());

deepCopy.get(0).setName("Charlie");
System.out.println(original.get(0).getName());  // "Alice" (не изменилось)
System.out.println(deepCopy.get(0).getName());  // "Charlie"

б) Через Cloneable интерфейс

public class User implements Cloneable {
    private String name;
    private int age;
    
    @Override
    public User clone() throws CloneNotSupportedException {
        return (User) super.clone();
    }
}

List<User> deepCopy = original.stream()
    .map(u -> {
        try {
            return u.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    })
    .collect(Collectors.toList());

в) Через JSON сериализацию (ObjectMapper)

ObjectMapper mapper = new ObjectMapper();
List<User> deepCopy = mapper.readValue(
    mapper.writeValueAsString(original),
    new TypeReference<List<User>>() {}
);

5. Неизменяемые копии (Immutable Collections)

List<String> original = new ArrayList<>(Arrays.asList("A", "B", "C"));

// Java 9+
List<String> unmodifiable = List.copyOf(original);
// unmodifiable.add("D");  // UnsupportedOperationException

// Java 8
List<String> immutable = Collections.unmodifiableList(
    new ArrayList<>(original)
);

// Set
Set<String> immutableSet = Set.copyOf(original);

// Map
Map<String, Integer> immutableMap = Map.copyOf(
    Map.of("A", 1, "B", 2)
);

6. Apache Commons Lang - ArrayUtils

List<String> original = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> copy = new ArrayList<>(original);

// Если нужна примитивная копия
int[] arr = {1, 2, 3};
int[] arrCopy = ArrayUtils.clone(arr);

Таблица сравнения методов

МетодТип копииСкоростьИспользование
new ArrayList<>(list)Поверхностная⚡⚡⚡ Быстро99% случаев
stream().collect()Поверхностная⚡⚡ НормальноФункциональный стиль
clone()Поверхностная⚡⚡⚡ БыстроЕсли есть Cloneable
stream().map(copy)Глубокая⚡ МедленноСложные объекты
List.copyOf()Неизменяемая⚡⚡Java 9+ для защиты
Collections.unmodifiableНеизменяемая⚡⚡⚡Java 8 и ниже

Когда что использовать

// Простые типы (String, Integer, etc.)
List<String> copy = new ArrayList<>(original);  // ✅ Проще и быстрее

// Нужна защита от изменений
List<String> safe = List.copyOf(original);  // ✅ Java 9+

// Сложные объекты с изменяемыми полями
List<User> deepCopy = original.stream()
    .map(User::new)
    .collect(Collectors.toList());  // ✅ Правильно

// Функциональный стиль с трансформацией
List<String> names = users.stream()
    .map(User::getName)
    .collect(Collectors.toList());  // ✅ Идеально

Главное правило: используй конструктор коллекции для простого копирования, Stream API для трансформаций, и copy constructor для объектов при глубоком копировании.

Как создать копию коллекции? | PrepBro