Java 8 fornisce un nuovo modo di chiamare il costruttore di copie o il metodo clone sugli elementi cani in modo elegante e compatto: stream , lambda e collezionisti .
Copia costruttore:
List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());
L'espressione Dog::new
è chiamata riferimento al metodo . Crea un oggetto funzione che chiama un costruttore su Dog
cui accetta un altro cane come argomento.
Metodo clone [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Ottenere un ArrayList
risultato
Oppure, se devi ArrayList
recuperarlo (nel caso in cui desideri modificarlo in seguito):
ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));
Aggiorna l'elenco in atto
Se non è necessario mantenere il contenuto originale dogs
dell'elenco, è possibile invece utilizzare il replaceAll
metodo e aggiornare l'elenco in posizione:
dogs.replaceAll(Dog::new);
Tutti gli esempi assumono import static java.util.stream.Collectors.*;
.
Collezionista per ArrayList
s
Il raccoglitore dell'ultimo esempio può essere trasformato in un metodo util. Dal momento che questa è una cosa così comune da fare, mi piace che sia breve e carina. Come questo:
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 su CloneNotSupportedException
:
Perché questa soluzione funzioni, il clone
metodo di Dog
non deve dichiarare che genera CloneNotSupportedException
. Il motivo è che all'argomento map
non è consentito generare eccezioni verificate.
Come questo:
// Note: Method is public and returns Dog, not Object
@Override
public Dog clone() /* Note: No throws clause here */ { ...
Questo non dovrebbe essere un grosso problema, dato che comunque è la migliore pratica. ( Effectice Java, ad esempio, fornisce questo consiglio.)
Grazie a Gustavo per averlo notato.
PS:
Se lo trovi più carino puoi invece usare la sintassi di riferimento del metodo per fare esattamente la stessa cosa:
List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());