Eu tenho um ArrayList
e quero copiá-lo exatamente. Eu uso classes de utilidade quando possível, supondo que alguém tenha passado algum tempo corrigindo. Então, naturalmente, acabo com a Collections
classe que contém um método de cópia.
Suponha que eu tenha o seguinte:
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);
Isso falha porque basicamente acha que b
não é grande o suficiente para aguentar a
. Sim, eu sei que b
tem tamanho 0, mas agora deve ser grande o suficiente, não deveria? Se eu tiver que preencher b
primeiro, isso Collections.copy()
se tornará uma função completamente inútil em minha mente. Então, exceto para programar uma função de cópia (que vou fazer agora), existe uma maneira adequada de fazer isso?
java
list
collections
copy
Jasper Floor
fonte
fonte
Respostas:
Chamando
cria uma cópia superficial de
a
dentrob
. Todos os elementos existirão dentrob
exatamente na mesma ordem em que estavama
(assumindo que havia uma ordem).Da mesma forma, chamar
também cria uma cópia superficial de
a
dentrob
. Se o primeiro parâmetro,b
,, não tiver capacidade suficiente (sem tamanho) para conter todosa
os elementos de, ele lançará umIndexOutOfBoundsException
. A expectativa é que não sejam necessárias alocaçõesCollections.copy
para o trabalho e, se houver, isso gera uma exceção. É uma otimização exigir que a coleção copiada seja pré-alocada (b
), mas geralmente não acho que o recurso valha a pena devido às verificações necessárias, dadas as alternativas baseadas em construtores, como a mostrada acima, que não têm efeitos colaterais estranhos.Para criar uma cópia profunda, o
List
mecanismo, por qualquer um dos mecanismos, teria que ter um conhecimento intrincado do tipo subjacente. No caso deString
s, que são imutáveis em Java (e .NET, nesse caso), você nem precisa de uma cópia profunda. No caso deMySpecialObject
, você precisa saber como fazer uma cópia profunda e isso não é uma operação genérica.Nota: a resposta originalmente aceita foi o principal resultado do
Collections.copy
Google e foi totalmente incorreta, conforme indicado nos comentários.fonte
b
tem uma capacidade de 3, mas um tamanho de 0. O fato deArrayList
ter algum tipo de capacidade de buffer é um detalhe de implementação - não faz parte daList
interface, portantoCollections.copy(List, List)
não a usa. Seria feio para um caso especialArrayList
.Como MrWiggles indicou, usar o construtor ArrayList que utiliza uma coleção é o caminho indicado no exemplo fornecido.
Para cenários mais complicados (que podem incluir seu código real), você pode achar úteis as coleções no Guava .
fonte
Apenas faça:
ArrayList tem um construtor que aceitará outra coleção para copiar os elementos de
fonte
String
objetos são imutáveis.A resposta de Stephen Katulka (resposta aceita) está errada (a segunda parte). Explica que
Collections.copy(b, a);
faz uma cópia profunda, o que não faz. Ambosnew ArrayList(a);
eCollections.copy(b, a);
apenas fazem uma cópia superficial. A diferença é que o construtor aloca nova memória, ecopy(...)
não o faz, o que a torna adequada nos casos em que você pode reutilizar matrizes, pois ela possui uma vantagem de desempenho.A API padrão Java tenta desencorajar o uso de cópias profundas, pois seria ruim se novos codificadores usassem isso regularmente, o que também pode ser um dos motivos pelos quais
clone()
não é público por padrão.O código fonte
Collections.copy(...)
pode ser visto na linha 552 em: http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/Collections-Jar-Zip-Logging-regex/java/util/ Collections.java.htmSe você precisar de uma cópia profunda, precisará iterar os itens manualmente, usando um loop for e clone () em cada objeto.
fonte
a maneira mais simples de copiar uma lista é transmiti-la ao construtor da nova lista:
b
será uma cópia rasa dea
Olhando a fonte
Collections.copy(List,List)
(eu nunca a tinha visto antes), parece ser para lidar com os elementos índice por índice. usarList.set(int,E)
assim o elemento 0 substituirá o elemento 0 na lista de destino, etc. etc. Não é particularmente claro nos javadocs que eu teria que admitir.fonte
não define o tamanho. Ele define a capacidade inicial (sendo quantos elementos pode caber antes de precisar redimensionar). Uma maneira mais simples de copiar neste caso é:
fonte
Como Hoijui menciona. A resposta selecionada de Stephen Katulka contém um comentário sobre Collections.copy que está incorreto. O autor provavelmente aceitou porque a primeira linha de código estava fazendo a cópia que ele queria. A chamada adicional para Collections.copy apenas copia novamente. (Resultando na cópia acontecendo duas vezes).
Aqui está o código para provar isso.
fonte
A maioria das respostas aqui não percebem o problema, o usuário deseja copiar os elementos da primeira lista para a segunda lista, os elementos da lista de destino são novos objetos e não fazem referência aos elementos da lista original. (significa alterar um elemento da segunda lista não deve alterar valores para o elemento correspondente da lista de origem.) Para os objetos mutáveis, não podemos usar o construtor ArrayList (Collection) porque ele se refere simplesmente ao elemento da lista original e não é copiado. Você precisa ter um clonador de lista para cada objeto ao copiar.
fonte
Por que você simplesmente não usa o
addAll
método:mesmo se você possui itens em b ou deseja pendurar alguns elementos depois dele, como:
fonte
Se você deseja copiar um ArrayList, copie-o usando:
fonte
As strings podem ser copiadas com profundidade
porque eles são imutáveis. Todos os outros Objetos não -> você precisa iterar e fazer uma cópia sozinho.
fonte
b
aponta para o mesmoString
objeto correspondente ema
. No entanto, isso não é importante porque, como você aponta, osString
objetos são imutáveis.fonte
Todos os outros Objetos não -> você precisa iterar e fazer uma cópia sozinho.
Para evitar esse implemento Cloneable.
....
fonte
A saída a seguir ilustra os resultados do uso do construtor de cópia e Collections.copy ():
A fonte do programa completo está aqui: cópia da lista Java . Mas a saída é suficiente para ver como o java.util.Collections.copy () se comporta.
fonte
E se você estiver usando o google goiaba, a solução de uma linha seria
Isso cria uma instância de lista de matriz mutável.
fonte
Com o Java 8 sendo nulo, você pode usar o seguinte código.
Ou usando um colecionador
fonte
Copiar não é inútil se você imaginar o caso de uso para copiar alguns valores em uma coleção existente. Ou seja, você deseja substituir os elementos existentes em vez de inserir.
Um exemplo: 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]
No entanto, eu esperaria um método de cópia que usasse parâmetros adicionais para o índice inicial da coleção de origem e destino, bem como um parâmetro para count.
Consulte Java BUG 6350752
fonte
Para entender por que Collections.copy () lança uma IndexOutOfBoundsException apesar de ter feito a matriz apoio da grande o suficiente lista de destinos (através da chamada size () na ListaDeOrigem), ver a resposta por Abhay Yadav nesta questão relacionada: Como copie um java.util.List para outro java.util.List
fonte