Рубрики
Без рубрики

Скопируйте список в другой список на Java

Изучите различные способы копирования списка в другой список на Java и распространенную ошибку, возникшую в этом процессе.

Автор оригинала: baeldung.

1. Обзор

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

Для ознакомления с использованием Коллекций , пожалуйста, обратитесь к этой статье здесь .

2. Конструктор

Простой способ скопировать List – это использовать конструктор, который принимает коллекцию в качестве аргумента:

List copy = new ArrayList<>(list);

Из-за того, что мы копируем ссылку здесь, а не клонируем объекты, каждое исправление, внесенное в один элемент, повлияет на оба списка.

По этой причине использование конструктора полезно для копирования неизменяемых объектов:

List copy = new ArrayList<>(list);

Integer – это неизменяемый класс, его значение устанавливается при создании экземпляра и никогда не может измениться.

Таким образом, ссылка Integer может быть разделена несколькими списками и потоками, и никто не может изменить ее значение.

3. Исключение ConcurrentAccessException списка

Распространенной проблемой при работе со списками является исключение ConcurrentAccessException . Это может означать, что мы изменяем список, пытаясь скопировать его, скорее всего, в другом потоке.

Чтобы устранить эту проблему, мы должны либо:

  • Используйте коллекцию, предназначенную для параллельного доступа
  • Заблокируйте коллекцию соответствующим образом, чтобы выполнить итерацию по ней
  • Найдите способ избежать необходимости копировать оригинальную коллекцию

Учитывая наш последний подход, он не является потокобезопасным. Таким образом, если мы хотим решить нашу проблему с первым вариантом , мы можем использовать CopyOnWriteArrayList , в котором все мутационные операции реализуются путем создания новой копии базового массива.

Для получения дополнительной информации, пожалуйста, обратитесь к этой статье .

В случае , если мы хотим заблокировать коллекцию |, можно использовать примитив блокировки для сериализации доступа на чтение/запись, например ReentrantReadWriteLock .

4. Добавьте Все

Другой подход к копированию элементов-использование метода addAll :

List copy = new ArrayList<>();
copy.addAll(list);

При использовании этого метода важно помнить, что, как и в случае с конструктором, содержимое обоих списков будет ссылаться на одни и те же объекты.

5. Коллекции.копия

Класс Collections состоит исключительно из статических методов, которые работают с коллекциями или возвращают их.

Одним из них является copy , для которого требуется список источников и список назначения, по крайней мере, такой же длины, как и источник.

Он будет поддерживать индекс каждого скопированного элемента в списке назначения, например исходного:

List source = Arrays.asList(1,2,3);
List dest = Arrays.asList(4,5,6);
Collections.copy(dest, source);

В приведенном выше примере все предыдущие элементы в списке dest были перезаписаны, поскольку оба списка имеют одинаковый размер.

В случае, если размер списка назначения больше, чем размер источника:

List source = Arrays.asList(1, 2, 3);
List dest = Arrays.asList(5, 6, 7, 8, 9, 10);
Collections.copy(dest, source);

Только три первых элемента были перезаписаны, в то время как остальные элементы в списке сохранены.

6. Использование Java 8

Эта версия Java открывает наши возможности, добавляя новые инструменты. Тот, который мы рассмотрим в следующих примерах, – это Поток :

List copy = list.stream()
  .collect(Collectors.toList());

Основными преимуществами этого способа являются возможность использования пропусков и фильтров. В следующем примере мы пропустим первый элемент:

List copy = list.stream()
  .skip(1)
  .collect(Collectors.toList());

Также можно фильтровать по длине строки | или сравнивая атрибут наших объектов:

List copy = list.stream()
  .filter(s -> s.length() > 10)
  .collect(Collectors.toList());
List flowers = list.stream()
  .filter(f -> f.getPetals() > 6)
  .collect(Collectors.toList());

Вероятно, мы хотим работать в нулевой безопасности:

List flowers = Optional.ofNullable(list)
  .map(List::stream)
  .orElseGet(Stream::empty)
  .collect(Collectors.toList());

И пропустить элемент, используя этот способ тоже:

List flowers = Optional.ofNullable(list)
  .map(List::stream).orElseGet(Stream::empty)
  .skip(1)
  .collect(Collectors.toList());

7. Использование Java 10

Наконец, одна из последних версий Java позволяет нам создать неизменяемый Список , содержащий элементы данной Коллекции:

List copy = List.copyOf(list);

8. Заключение