Как скопировать файл 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, это вызовет параллельное исключение в вашем коде, независимо от того, будет ли он одним потоком или несколькими потоками.