Как скопировать файл java.util.List в другой файл java.util.List
У меня есть List<SomeBean>
, который заполняется из веб-службы. Я хочу скопировать/клонировать содержимое этого списка в пустой список того же типа. Поиск Google для копирования списка предложил мне использовать метод Collections.copy()
. Во всех примерах, которые я видел, список адресатов должен был содержать точное количество элементов для копирования.
Поскольку список, который я использую, заполняется через веб-службу и содержит сотни объектов, я не могу использовать вышеупомянутую технику. Или я использую это неправильно??!! В любом случае, чтобы заставить его работать, я попытался сделать что-то подобное, но у меня все еще есть IndexOutOfBoundsException
.
List<SomeBean> wsList = app.allInOne(template);
List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList.size());
Collections.copy(wsListCopy,wsList);
System.out.println(wsListCopy.size());
Я попытался использовать wsListCopy=wsList.subList(0, wsList.size())
, но позже я получил ConcurrentAccessException
в коде. Хит и испытание.:)
В любом случае, мой вопрос прост, как я могу скопировать весь контент моего списка в другой список? Не через итерацию, конечно.
Ответы
Ответ 1
Просто используйте это:
List<SomeBean> newList = new ArrayList<SomeBean>(otherList);
Примечание: все еще не потокобезопасно, если вы изменяете otherList
из другого потока, тогда вы можете сделать это otherList
(и даже newList
) CopyOnWriteArrayList
, например, или используйте примитив блокировки, например ReentrantReadWriteLock, чтобы сериализовать доступ для чтения и записи к любым спискам одновременно.
Ответ 2
Это действительно хороший способ для Java 8:
List<String> list2 = list1.stream().collect(Collectors.toList());
Конечно, преимущество заключается в том, что вы можете фильтровать и пропускать только копию части списка.
например.
//don't copy the first element
List<String> list2 = list1.stream().skip(1).collect(Collectors.toList());
Ответ 3
originalArrayList.addAll(copyArrayofList);
Помните, что при использовании метода addAll() для копирования содержимое списков массивов (originalArrayList и copyArrayofList) будет добавлено в список, поэтому если вы изменить любой из них, то copyArrayofList также будет отражать то же изменение.
Если вам не нужен побочный эффект, вам нужно скопировать каждый элемент из originalArrayList в copyArrayofList, например, используя цикл for или while.
Ответ 4
Я попытался сделать что-то подобное, но у меня все еще есть исключение IndexOutOfBoundsException.
У меня есть ConcurrentAccessException
Это означает, что вы изменяете список во время его копирования, скорее всего, в другом потоке. Чтобы исправить это, вам нужно либо
-
используйте коллекцию, предназначенную для одновременного доступа.
-
заблокируйте коллекцию соответствующим образом, чтобы вы могли перебирать ее (или разрешить вам вызывать метод, который делает это для вас)
-
найдите, чтобы не нужно копировать исходный список.
Ответ 5
Существует другой метод с Java 8 с нулевой безопасностью.
List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
.map(List::stream)
.orElseGet(Stream::empty)
.collect(Collectors.toList());
Если вы хотите пропустить один элемент.
List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
.map(List::stream)
.orElseGet(Stream::empty)
.skip(1)
.collect(Collectors.toList());
Ответ 6
Начиная с Java 10:
List<E> oldList = List.of();
List<E> newList = List.copyOf(oldList);
List.copyOf()
возвращает неизменяемый List
содержащий элементы данной Collection
.
Данная Collection
не должна быть null
и не должна содержать никаких null
элементов.
Если вы хотите создать глубокую копию List
, вы можете найти много хороших ответов здесь.
Ответ 7
Я попробовал нечто подобное и смог воспроизвести проблему (IndexOutOfBoundsException). Ниже приведены мои выводы:
1) Реализация Collections.copy(destList, sourceList) сначала проверяет размер списка адресатов, вызывая метод size(). Поскольку вызов метода size() всегда возвращает количество элементов в списке (в данном случае 0), конструктор ArrayList (емкость) обеспечивает только начальную емкость массива подкачки, и это не имеет никакого отношения к размер списка. Следовательно, мы всегда получаем исключение IndexOutOfBoundsException.
2) Относительно простой способ - использовать конструктор, который берет коллекцию в качестве аргумента:
List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList);
Ответ 8
У меня была такая же проблема ConcurrentAccessException, а mysolution была:
List<SomeBean> tempList = new ArrayList<>();
for (CartItem item : prodList) {
tempList.add(item);
}
prodList.clear();
prodList = new ArrayList<>(tempList);
Таким образом, он работает только одна операция в то время и избегает Exeption...
Ответ 9
re: indexOutOfBoundsException
, ваши аргументы в подсписке - проблема; вам нужно завершить подсписку размером 1. Будучи основанным на нуле, последний элемент списка всегда имеет размер 1, в позиции размера нет элемента, поэтому ошибка.
Ответ 10
Вы можете использовать addAll().
например: wsListCopy.addAll(wsList);
Ответ 11
Я не вижу правильного ответа. Если вы хотите глубокое копирование, вам нужно итерировать и копировать объект вручную (вы можете использовать конструктор копирования).
Ответ 12
Если вы не хотите, чтобы изменения в одном списке влияли на другой список, попробуйте это. Это сработало для меня
Надеюсь это поможет.
public class MainClass {
public static void main(String[] a) {
List list = new ArrayList();
list.add("A");
List list2 = ((List) ((ArrayList) list).clone());
System.out.println(list);
System.out.println(list2);
list.clear();
System.out.println(list);
System.out.println(list2);
}
}
> Output:
[A]
[A]
[]
[A]
Ответ 13
Функция subList - это трюк, возвращаемый объект все еще находится в исходном списке.
поэтому, если вы выполняете какую-либо операцию в subList, это вызовет параллельное исключение в вашем коде, независимо от того, будет ли он одним потоком или несколькими потоками.