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 Dogqual leva outro cão como argumento.
Método de clone [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Obtendo um ArrayListcomo resultado
Ou, se você precisar receber uma ArrayListresposta (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 dogslista, poderá usar o replaceAllmétodo e atualizar a lista:
dogs.replaceAll(Dog::new);
Todos os exemplos assumem import static java.util.stream.Collectors.*;.
Coletor para ArrayLists
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 clonemétodo de Dog não deve declarar que é lançado CloneNotSupportedException. O motivo é que o argumento para mapnã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());