Java 8 proporciona una nueva forma de llamar al constructor de copias o al método de clonación en los elementos perros de forma elegante y compacta: Streams , lambdas y recopiladores .
Copiar constructor:
List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());
La expresión Dog::newse llama referencia de método . Crea un objeto de función que llama a un constructor en el Dogque toma otro perro como argumento.
Método de clonación [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Obteniendo un ArrayListresultado
O, si tiene que obtener un ArrayListrespaldo (en caso de que quiera modificarlo más adelante):
ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));
Actualice la lista en su lugar
Si no necesita conservar el contenido original de la dogslista, puede utilizar el replaceAllmétodo y actualizar la lista en su lugar:
dogs.replaceAll(Dog::new);
Todos los ejemplos asumen import static java.util.stream.Collectors.*;.
Coleccionista para ArrayLists
El recopilador del último ejemplo puede convertirse en un método util. Como esto es algo muy común, personalmente me gusta que sea corto y bonito. Me gusta esto:
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 solución funcione, el clonemétodo de Dog no debe declarar que arroja CloneNotSupportedException. La razón es que mapno se permite al argumento lanzar ninguna excepción marcada.
Me gusta esto:
// Note: Method is public and returns Dog, not Object
@Override
public Dog clone() /* Note: No throws clause here */ { ...
Sin embargo, esto no debería ser un gran problema, ya que es la mejor práctica de todos modos. ( Effectice Java, por ejemplo, da este consejo).
Gracias a Gustavo por notar esto.
PD:
Si lo encuentra más bonito, puede usar la sintaxis de referencia del método para hacer exactamente lo mismo:
List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());