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::new
se llama referencia de método . Crea un objeto de función que llama a un constructor en el Dog
que toma otro perro como argumento.
Método de clonación [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Obteniendo un ArrayList
resultado
O, si tiene que obtener un ArrayList
respaldo (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 dogs
lista, puede utilizar el replaceAll
método y actualizar la lista en su lugar:
dogs.replaceAll(Dog::new);
Todos los ejemplos asumen import static java.util.stream.Collectors.*;
.
Coleccionista para ArrayList
s
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 clone
método de Dog
no debe declarar que arroja CloneNotSupportedException
. La razón es que map
no 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());