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:
List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());
A expressão Dog::new
é chamada de referência de método . Ele cria um objeto de função que chama um construtor no Dog
qual leva outro cão como argumento.
Método de clone [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Obtendo um ArrayList
como resultado
Ou, se você precisar receber uma ArrayList
resposta (caso queira modificá-lo posteriormente):
ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));
Atualize a lista no local
Se você não precisar manter o conteúdo original da dogs
lista, poderá usar o replaceAll
método e atualizar a lista:
dogs.replaceAll(Dog::new);
Todos os exemplos assumem import static java.util.stream.Collectors.*;
.
Coletor para ArrayList
s
O 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:
ArrayList<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toArrayList());
public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
return Collectors.toCollection(ArrayList::new);
}
[1] Nota sobre CloneNotSupportedException
:
Para que esta solução funcione, o clone
método de Dog
não deve declarar que é lançado CloneNotSupportedException
. O motivo é que o argumento para map
não tem permissão para lançar nenhuma exceção verificada.
Como isso:
// Note: Method is public and returns Dog, not Object
@Override
public Dog clone() /* Note: No throws clause here */ { ...
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:
List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());