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::new
wird als Methodenreferenz bezeichnet . Es wird ein Funktionsobjekt erstellt, das einen Konstruktor aufruft, für den ein Dog
anderer Hund als Argument verwendet wird.
Klonmethode [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Ein Angebot ArrayList
als Ergebnis
Oder wenn Sie eine Rückerstattung ArrayList
benö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 dogs
Liste nicht beibehalten müssen, können Sie stattdessen die replaceAll
Methode 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 ArrayList
s
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 map
keine 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());