Java 8 предоставляет новый способ элегантного и компактного вызова конструктора копирования или метода клонирования на элементах: Потоки , lambdas и коллекторы .
Конструктор копирования:
List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());
Выражение Dog::new
называется ссылка на метод . Он создает объект функции, который вызывает конструктор в Dog
, который принимает в качестве аргумента другую собаку.
Метод клонирования [1]:
List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());
Получение ArrayList
в результате
Или, если вам нужно вернуть ArrayList
(на случай, если вы захотите изменить его позже):
ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));
Обновить список на месте
Если вам не нужно сохранять исходное содержимое списка dogs
, вы можете вместо этого использовать метод replaceAll
и обновить список на месте:
dogs.replaceAll(Dog::new);
Все примеры предполагают import static java.util.stream.Collectors.*;
.
Коллектор для ArrayList
с
Сборщик из последнего примера можно превратить в метод util. Поскольку это настолько распространенная вещь, мне лично нравится, чтобы она была короткой и красивой. Как это:
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] Примечание к CloneNotSupportedException
:
Чтобы это решение работало, метод clone
Dog
не должен объявлять, что он выбрасывает CloneNotSupportedException
. Причина в том, что аргумент map
не может генерировать какие-либо проверенные исключения.
Как это:
// Note: Method is public and returns Dog, not Object
@Override
public Dog clone() /* Note: No throws clause here */ { ...
Однако это не должно быть большой проблемой, так как в любом случае это лучшая практика. ( Effectice Java , например, дает этот совет.)
Спасибо Густаво за то, что отметили это.
PS:
Если вы находите это красивее, вы можете вместо этого использовать синтаксис ссылки на метод, чтобы сделать то же самое:
List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());