Как скопировать список коллекций Java - PullRequest
135 голосов
/ 27 марта 2009

У меня есть ArrayList, и я хочу точно его скопировать. Я использую служебные классы, когда это возможно, исходя из предположения, что кто-то потратил некоторое время, чтобы исправить это. Естественно, я получаю класс Collections, который содержит метод копирования.

Предположим, у меня есть следующее:

List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a.size());

Collections.copy(b,a);

Это терпит неудачу, потому что в основном он думает, что b недостаточно большой, чтобы вместить a. Да, я знаю, что b имеет размер 0, но он должен быть достаточно большим, не так ли? Если мне сначала нужно заполнить b, тогда Collections.copy() становится совершенно бесполезной функцией в моем уме. Итак, кроме программирования функции копирования (которую я собираюсь сделать сейчас), есть ли правильный способ сделать это?

Ответы [ 18 ]

3 голосов
/ 27 марта 2009

Если вы хотите скопировать ArrayList, скопируйте его с помощью:

List b = new ArrayList();
b.add("aa");
b.add("bb");

List a = new ArrayList(b);
3 голосов
/ 05 апреля 2011

Строки могут быть глубоко скопированы с

List<String> b = new ArrayList<String>(a);

потому что они неизменны. Любой другой объект не -> вам нужно перебрать и сделать копию самостоятельно.

1 голос
/ 14 декабря 2017

Поскольку Java 8 не содержит нулевых значений, вы можете использовать следующий код.

List<String> b = Optional.ofNullable(a)
                         .map(list -> (List<String>) new ArrayList<>(list))
                         .orElseGet(Collections::emptyList);

Или с помощью коллектора

List<String> b = Optional.ofNullable(a)
                         .map(List::stream)
                         .orElseGet(Stream::empty)
                         .collect(Collectors.toList())
1 голос
/ 30 июля 2015

Следующий вывод иллюстрирует результаты использования конструктора копирования и Collections.copy ():

Copy [1, 2, 3] to [1, 2, 3] using copy constructor.

Copy [1, 2, 3] to (smaller) [4, 5]
java.lang.IndexOutOfBoundsException: Source does not fit in dest
        at java.util.Collections.copy(Collections.java:556)
        at com.farenda.java.CollectionsCopy.copySourceToSmallerDest(CollectionsCopy.java:36)
        at com.farenda.java.CollectionsCopy.main(CollectionsCopy.java:14)

Copy [1, 2] to (same size) [3, 4]
source: [1, 2]
destination: [1, 2]

Copy [1, 2] to (bigger) [3, 4, 5]
source: [1, 2]
destination: [1, 2, 5]

Copy [1, 2] to (unmodifiable) [4, 5]
java.lang.UnsupportedOperationException
        at java.util.Collections$UnmodifiableList.set(Collections.java:1311)
        at java.util.Collections.copy(Collections.java:561)
        at com.farenda.java.CollectionsCopy.copyToUnmodifiableDest(CollectionsCopy.java:68)
        at com.farenda.java.CollectionsCopy.main(CollectionsCopy.java:20)

Источник полной программы находится здесь: Копия списка Java . Но вывода достаточно, чтобы увидеть, как ведет себя java.util.Collections.copy ().

1 голос
/ 28 ноября 2011

Каждый другой объект не -> вам нужно выполнить итерацию и сделать копию самостоятельно.

Чтобы избежать этого, используйте Cloneable.

public class User implements Serializable, Cloneable {

    private static final long serialVersionUID = 1L;

    private String user;
    private String password;
    ...

    @Override
    public Object clone() {
        Object o = null;
        try {
          o = super.clone();
        } catch(CloneNotSupportedException e) {
        }
        return o;
     }
 }

....

  public static void main(String[] args) {

      List<User> userList1 = new ArrayList<User>();

      User user1 = new User();
      user1.setUser("User1");
      user1.setPassword("pass1");
      ...

      User user2 = new User();
      user2.setUser("User2");
      user2.setPassword("pass2");
      ...

      userList1 .add(user1);
      userList1 .add(user2);

      List<User> userList2 = new ArrayList<User>();


      for(User u: userList1){
          u.add((User)u.clone());
      }

      //With this you can avoid 
      /*
        for(User u: userList1){
            User tmp = new User();
            tmp.setUser(u.getUser);
            tmp.setPassword(u.getPassword);
            ...
            u.add(tmp);               
        }
       */

  }
0 голосов
/ 27 апреля 2016

Чтобы понять, почему Collections.copy () генерирует исключение IndexOutOfBoundsException, хотя вы сделали достаточно большой резервный массив списка назначения (с помощью вызова size () для sourceList), посмотрите ответ Абхая Ядава в этом связанном вопросе : Как скопировать java.util.List в другой java.util.List

0 голосов
/ 11 октября 2013

И если вы используете Google Guava, решение в одну строку будет

List<String> b = Lists.newArrayList(a);

Это создает экземпляр списка изменяемых массивов.

0 голосов
/ 27 марта 2009

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

Пример: a = [1,2,3,4,5] b = [2,2,2,2,3,3,3,3,3,4,4,4,] a.copy (b) = [1,2,3,4,5,3,3,3,3,4,4,4]

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

См. Java BUG 6350752

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...