Como posso clonar um ArrayList
e também clonar seus itens em Java?
Por exemplo, eu tenho:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
E eu esperaria que os objetos clonedList
não sejam os mesmos da lista de cães.
java
collections
clone
deep-copy
palig
fonte
fonte
Respostas:
Você precisará iterar nos itens e cloná-los um por um, colocando os clones em sua matriz de resultados à medida que avança.
Para que isso funcione, obviamente, você precisará que sua
Dog
classe implemente aCloneable
interface e substitua oclone()
método.fonte
Eu, pessoalmente, adicionaria um construtor ao Dog:
Em seguida, basta iterar (como mostrado na resposta de Varkhan):
Acho que a vantagem disso é que você não precisa se meter com o material Cloneable quebrado em Java. Também corresponde à maneira como você copia as coleções Java.
Outra opção poderia ser escrever sua própria interface ICloneable e usá-la. Dessa forma, você pode escrever um método genérico para clonagem.
fonte
cloneList(List<Object>)
ouDog(Object)
?Todas as coleções padrão têm construtores de cópia. Usa-os.
clone()
foi projetado com vários erros (consulte esta pergunta ), por isso é melhor evitá-lo.Do Effective Java 2nd Edition , item 11: Substituir clone criteriosamente
Este livro também descreve as muitas vantagens que os construtores de cópias têm sobre o Cloneable / clone.
Considere outro benefício do uso de construtores de cópia: suponha que você tenha um
HashSet s
e deseje copiá-lo como aTreeSet
. O método clone não pode oferecer essa funcionalidade, mas é fácil com um construtor de conversão:new TreeSet(s)
.fonte
O Java 8 fornece uma nova maneira de chamar o método construtor de cópia ou clone no elemento dog de maneira elegante e compacta: Streams , lambdas e coletores .
Copiar construtor:
A expressão
Dog::new
é chamada de referência de método . Ele cria um objeto de função que chama um construtor noDog
qual leva outro cão como argumento.Método de clone [1]:
Obtendo um
ArrayList
como resultadoOu, se você precisar receber uma
ArrayList
resposta (caso queira modificá-lo posteriormente):Atualize a lista no local
Se você não precisar manter o conteúdo original da
dogs
lista, poderá usar oreplaceAll
método e atualizar a lista:Todos os exemplos assumem
import static java.util.stream.Collectors.*;
.Coletor para
ArrayList
sO coletor do último exemplo pode ser transformado em um método util. Como isso é algo comum, eu pessoalmente gosto de ser curto e bonito. Como isso:
[1] Nota sobre
CloneNotSupportedException
:Para que esta solução funcione, o
clone
método deDog
não deve declarar que é lançadoCloneNotSupportedException
. O motivo é que o argumento paramap
não tem permissão para lançar nenhuma exceção verificada.Como isso:
No entanto, esse não deve ser um grande problema, pois, de qualquer maneira, essa é a melhor prática. (O Effectice Java, por exemplo, dá esse conselho.)
Obrigado a Gustavo por observar isso.
PS:
Se você achar mais bonito, poderá usar a sintaxe de referência do método para fazer exatamente a mesma coisa:
fonte
List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d)));
parallel
chamada faz com queclonedDogs.add
sejam chamados de vários threads ao mesmo tempo. As versões utilizadascollect
são seguras para threads. Essa é uma das vantagens do modelo funcional da biblioteca de fluxos, o mesmo código pode ser usado para fluxos paralelos.Unhandled exception type CloneNotSupportedException
nod.clone()
. Declarar a exceção ou capturá-la não a resolve.Dog
neste exemplo) não suporta a clonagem. Tem certeza de que implementa aClonable
interface?Basicamente, existem três maneiras sem iterar manualmente,
1 Usando o construtor
2 Usando
addAll(Collection<? extends E> c)
3 Usando o
addAll(int index, Collection<? extends E> c)
método com oint
parâmetroNota: O comportamento dessas operações será indefinido se a coleção especificada for modificada enquanto a operação estiver em andamento.
fonte
Eu acho que a resposta verde atual é ruim , por que você pode perguntar?
A maneira como a serialização também é ruim, talvez você precise adicionar Serializable em todo o lugar.
Então qual é a solução:
Biblioteca de Deep Clonagem Java A biblioteca de clonagem é uma pequena biblioteca java de código aberto (licença apache) que clona profundamente objetos. Os objetos não precisam implementar a interface Cloneable. De fato, essa biblioteca pode clonar QUALQUER objeto java. Pode ser usado, por exemplo, em implementações de cache, se você não quiser que o objeto em cache seja modificado ou sempre que desejar criar uma cópia profunda dos objetos.
Confira em https://github.com/kostaskougios/cloning
fonte
Eu encontrei uma maneira, você pode usar o json para serializar / desserializar a lista. A lista serializada não contém referência ao objeto original quando não serializada.
Usando o gson:
Você pode fazer isso usando jackson e qualquer outra biblioteca json também.
fonte
Eu sempre usei essa opção:
fonte
Você precisará clonar
ArrayList
manualmente (iterando sobre ele e copiando cada elemento para um novoArrayList
), porqueclone()
não fará isso por você. A razão para isso é que os objetos contidos noArrayList
podem nãoClonable
se implementar .Edit : ... e é exatamente isso que o código de Varkhan faz.
fonte
Uma maneira desagradável é fazê-lo com reflexão. Algo assim funcionou para mim.
fonte
original
objetos de classes diferentes, achocloneMethod.invoke
que falhará com uma exceção quando for invocado com o tipo errado de objeto. Por isso, pode ser melhor recuperar um clone específicoMethod
para cada objeto. Ou use o método clone emObject
(mas, como esse está protegido, pode falhar em mais casos).Isso irá copiar profundamente cada cão
fonte
Os outros pôsteres estão corretos: você precisa iterar a lista e copiar em uma nova lista.
No entanto ... Se os objetos na lista são imutáveis - você não precisa cloná-los. Se o seu objeto tiver um gráfico complexo, ele também precisará ser imutável.
O outro benefício da imutabilidade é que eles também são seguros para threads.
fonte
Aqui está uma solução usando um tipo de modelo genérico:
fonte
para você, os objetos substituem o método clone ()
e chame .clone () para Vector obj ou ArraiList obj ....
fonte
Maneira fácil usando commons-lang-2.3.jar que biblioteca de java para clonar lista
link para download commons-lang-2.3.jar
Como usar
Espero que este possa ser útil.
: D
fonte
O pacote
import org.apache.commons.lang.SerializationUtils;
Existe um método
SerializationUtils.clone(Object);
Exemplo
fonte
Acabei de desenvolver uma lib capaz de clonar um objeto de entidade e um objeto java.util.List. Faça o download do jar em https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U e use o método estático cloneListObject (lista de lista). Este método não apenas clona a lista, mas também todos os elementos da entidade.
fonte
O abaixo funcionou para mim ..
em Dog.java
Aqui, a nova lista criada a partir do método createCopy é criada por meio de SerializationUtils.clone (). Portanto, qualquer alteração feita na nova lista não afetará a lista original
fonte
Acho que encontrei uma maneira muito fácil de fazer uma cópia profunda do ArrayList. Supondo que você deseja copiar um String ArrayList arrayA.
Deixe-me saber se não funcionar para você.
fonte