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 Dogcui accetta un altro cane come argomento.
Metodo clone [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Ottenere un ArrayListrisultato
Oppure, se devi ArrayListrecuperarlo (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 dogsdell'elenco, è possibile invece utilizzare il replaceAllmetodo e aggiornare l'elenco in posizione:
dogs.replaceAll(Dog::new);
Tutti gli esempi assumono import static java.util.stream.Collectors.*;.
Collezionista per ArrayLists
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 clonemetodo di Dog non deve dichiarare che genera CloneNotSupportedException. Il motivo è che all'argomento mapnon è 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());