2008-09-10 11 views
129

У меня есть ArrayList<String>, что я хотел бы вернуть копию. ArrayList имеет метод клон имеет следующую подпись:Как клонировать общий список в Java?

public Object clone() 

После того как я называю этот метод, как я бросил возвращаемый объект обратно в ArrayList<String>?

+14

Нет, это действительный вопрос. Java не поддерживает «истинные» дженерики, с стиранием типа runtime и все, поэтому эти детали могут быть сложными. Кроме того, интерфейс Cloneable и механизм метода Object.clone() аналогично запутывают. – 2008-09-10 18:19:42

+0

ОК, я в основном делаю C#, где это очень просто. Пожалуйста, дайте мне знать, если вы хотите, чтобы я удалил комментарии по этому вопросу. – Espo 2008-09-10 18:21:25

+1

Вы можете оставить свой комментарий. Я думаю, мои правки объяснили, с чем я столкнулся. – 2008-09-10 18:23:56

ответ

50
ArrayList newArrayList = (ArrayList) oldArrayList.clone(); 
+35

Это будет отлично работать для строк (это вопрос, который задал вопрос), но стоит отметить, что ArrayList.clone выполнит мелкую копию, поэтому, если в списке есть изменяемые объекты, они не будут клонированы (и изменяются один из одного списка также изменит этот код в другом списке. – pkaeding 2008-09-10 18:25:34

+43

Вам следует избегать использования необработанных типов во всем, кроме устаревшего кода. Вам лучше использовать `ArrayList newArrayList = (ArrayList ) oldArrayList.clone();` – cdmckay 2009-03-01 03:34:56

1
ArrayList first = new ArrayList(); 
ArrayList copy = (ArrayList) first.clone(); 
5

Я считаю, используя addAll работает отлично.

ArrayList(String) copy = new ArrayList(String)(); 
copy.addAll(original); 

круглые скобки используются вместо синтаксиса дженериков

2

Это также должно работать:

ArrayList<String> orig = new ArrayList<String>(); 
ArrayList<String> copy = (ArrayList<String>) orig.clone() 
14

Я думаю, что это следует сделать трюк с использованием API Коллекции:

Примечание : метод копирования выполняется в линейном времени.

//assume oldList exists and has data in it. 
List<String> newList = new ArrayList<String>(); 
Collections.copy(newList, oldList); 
276

Зачем вам клонировать? Создание нового списка обычно имеет больше смысла.

List<String> strs; 
... 
List<String> newStrs = new ArrayList<>(strs); 

Работа выполнена.

16

Следует иметь в виду, что Object.clone() имеет некоторые серьезные проблемы, и его использование в большинстве случаев не рекомендуется. Пожалуйста, см. Пункт 11, от «Effective Java» Джошуа Блоха за полный ответ. Я считаю, что вы можете безопасно использовать Object.clone() для массивов примитивных типов, но помимо этого вам нужно быть разумным в правильном использовании и переопределении клона. Вероятно, вам лучше определить конструктор копирования или статический заводский метод, который явно клонирует объект в соответствии с вашей семантикой.

2

Будьте очень осторожны при клонировании ArrayLists. Клонирование в java неглубоко. Это означает, что он будет клонировать самого Arraylist, а не его членов. Поэтому, если у вас есть ArrayList X1 и клонируйте его в X2, любое изменение в X2 также будет отображаться в X1 и наоборот. Когда вы клонируете, вы создадите новый ArrayList с указателями на те же элементы в оригинале.

0

Я не профессионал java, но у меня такая же проблема, и я попытался решить этот метод. (Предположим, что T имеет конструктор копирования).

public static <T extends Object> List<T> clone(List<T> list) { 
     try { 
      List<T> c = list.getClass().newInstance(); 
      for(T t: list) { 
      T copy = (T) t.getClass().getDeclaredConstructor(t.getclass()).newInstance(t); 
      c.add(copy); 
      } 
      return c; 
     } catch(Exception e) { 
      throw new RuntimeException("List cloning unsupported",e); 
     } 
} 
20

Это код, я использую для этого:

ArrayList copy = new ArrayList (original.size()); 
Collections.copy(copy, original); 

Надежда полезна для вас

2

Моя функция клонировать список с типом:

public static <T extends Object> List<T> cloneList(List<T> list) { 
    return ((List<T>) ((ArrayList<T>) list).clone()); 
} 
2

Для клона общий интерфейс, такой как java.util.List, вам просто нужно его бросить.здесь вы пример:

List list = new ArrayList(); 
List list2 = ((List) ((ArrayList) list).clone()); 

Это немного сложнее, но это работает, если вы ограничены вернуть интерфейс List, так что каждый после вы можете реализовать свой список каждый раз, когда он хочет.

Я знаю, что этот ответ близок к окончательному ответу, но мой ответ отвечает, как сделать все, что в то время как вы работаете с List -The родовые не между родителями ArrayList

12

С Java 8 может быть клонирован с поток.

import static java.util.stream.Collectors.toList; 

...

List<AnObject> clone = myList.stream().collect(toList()); 
4

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

ImmutableList.copyOf(list);