Java 8 bietet eine neue Möglichkeit, die Kopierkonstruktor- oder Klonmethode für die Elementhunde elegant und kompakt aufzurufen: Streams , Lambdas und Sammler .
Konstruktor kopieren:
List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());
Der Ausdruck Dog::newwird als Methodenreferenz bezeichnet . Es wird ein Funktionsobjekt erstellt, das einen Konstruktor aufruft, für den ein Doganderer Hund als Argument verwendet wird.
Klonmethode [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Ein Angebot ArrayListals Ergebnis
Oder wenn Sie eine Rückerstattung ArrayListbenötigen (falls Sie diese später ändern möchten):
ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));
Aktualisieren Sie die Liste
Wenn Sie den ursprünglichen Inhalt der dogsListe nicht beibehalten müssen, können Sie stattdessen die replaceAllMethode verwenden und die Liste an Ort und Stelle aktualisieren:
dogs.replaceAll(Dog::new);
Alle Beispiele gehen davon aus import static java.util.stream.Collectors.*;.
Sammler für ArrayLists
Der Kollektor aus dem letzten Beispiel kann zu einer util-Methode gemacht werden. Da dies so häufig vorkommt, mag ich es persönlich, wenn es kurz und hübsch ist. So was:
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] Hinweis zu CloneNotSupportedException:
Damit diese Lösung funktioniert clone, Dog darf die Methode von nicht deklarieren, dass sie ausgelöst wird CloneNotSupportedException. Der Grund ist, dass das Argument to mapkeine geprüften Ausnahmen auslösen darf.
So was:
// Note: Method is public and returns Dog, not Object
@Override
public Dog clone() /* Note: No throws clause here */ { ...
Dies sollte jedoch kein großes Problem sein, da dies ohnehin die beste Vorgehensweise ist. ( Effectice Java zum Beispiel gibt diesen Rat.)
Vielen Dank an Gustavo, der dies bemerkt hat.
PS:
Wenn Sie es schöner finden, können Sie stattdessen die Methodenreferenzsyntax verwenden, um genau dasselbe zu tun:
List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());