1. Обзор
В этом кратком руководстве мы покажем различные способы копирования Списка в другой Список и общую ошибку, возникшую в процессе.
Для ознакомления с использованием Коллекций , пожалуйста, обратитесь к этой статье здесь .
2. Конструктор
Простой способ скопировать List – это использовать конструктор, который принимает коллекцию в качестве аргумента:
Listcopy = new ArrayList<>(list);
Из-за того, что мы копируем ссылку здесь, а не клонируем объекты, каждое исправление, внесенное в один элемент, повлияет на оба списка.
По этой причине использование конструктора полезно для копирования неизменяемых объектов:
Listcopy = new ArrayList<>(list);
Integer – это неизменяемый класс, его значение устанавливается при создании экземпляра и никогда не может измениться.
Таким образом, ссылка Integer может быть разделена несколькими списками и потоками, и никто не может изменить ее значение.
3. Исключение ConcurrentAccessException списка
Распространенной проблемой при работе со списками является исключение ConcurrentAccessException . Это может означать, что мы изменяем список, пытаясь скопировать его, скорее всего, в другом потоке.
Чтобы устранить эту проблему, мы должны либо:
- Используйте коллекцию, предназначенную для параллельного доступа
- Заблокируйте коллекцию соответствующим образом, чтобы выполнить итерацию по ней
- Найдите способ избежать необходимости копировать оригинальную коллекцию
Учитывая наш последний подход, он не является потокобезопасным. Таким образом, если мы хотим решить нашу проблему с первым вариантом , мы можем использовать CopyOnWriteArrayList , в котором все мутационные операции реализуются путем создания новой копии базового массива.
Для получения дополнительной информации, пожалуйста, обратитесь к этой статье .
В случае , если мы хотим заблокировать коллекцию |, можно использовать примитив блокировки для сериализации доступа на чтение/запись, например ReentrantReadWriteLock .
4. Добавьте Все
Другой подход к копированию элементов-использование метода addAll :
Listcopy = new ArrayList<>(); copy.addAll(list);
При использовании этого метода важно помнить, что, как и в случае с конструктором, содержимое обоих списков будет ссылаться на одни и те же объекты.
5. Коллекции.копия
Класс Collections состоит исключительно из статических методов, которые работают с коллекциями или возвращают их.
Одним из них является copy , для которого требуется список источников и список назначения, по крайней мере, такой же длины, как и источник.
Он будет поддерживать индекс каждого скопированного элемента в списке назначения, например исходного:
Listsource = Arrays.asList(1,2,3); List dest = Arrays.asList(4,5,6); Collections.copy(dest, source);
В приведенном выше примере все предыдущие элементы в списке dest были перезаписаны, поскольку оба списка имеют одинаковый размер.
В случае, если размер списка назначения больше, чем размер источника:
Listsource = Arrays.asList(1, 2, 3); List dest = Arrays.asList(5, 6, 7, 8, 9, 10); Collections.copy(dest, source);
Только три первых элемента были перезаписаны, в то время как остальные элементы в списке сохранены.
6. Использование Java 8
Эта версия Java открывает наши возможности, добавляя новые инструменты. Тот, который мы рассмотрим в следующих примерах, – это Поток :
Listcopy = list.stream() .collect(Collectors.toList());
Основными преимуществами этого способа являются возможность использования пропусков и фильтров. В следующем примере мы пропустим первый элемент:
Listcopy = list.stream() .skip(1) .collect(Collectors.toList());
Также можно фильтровать по длине строки | или сравнивая атрибут наших объектов:
Listcopy = list.stream() .filter(s -> s.length() > 10) .collect(Collectors.toList());
Listflowers = list.stream() .filter(f -> f.getPetals() > 6) .collect(Collectors.toList());
Вероятно, мы хотим работать в нулевой безопасности:
Listflowers = Optional.ofNullable(list) .map(List::stream) .orElseGet(Stream::empty) .collect(Collectors.toList());
И пропустить элемент, используя этот способ тоже:
Listflowers = Optional.ofNullable(list) .map(List::stream).orElseGet(Stream::empty) .skip(1) .collect(Collectors.toList());
7. Использование Java 10
Наконец, одна из последних версий Java позволяет нам создать неизменяемый Список , содержащий элементы данной Коллекции:
Listcopy = List.copyOf(list);