Java 8 предоставляет новый способ элегантного и компактного вызова конструктора копирования или метода клонирования на элементах Dogs: потоки , лямбды и коллекторы .
Скопируйте конструктор:
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
. Причина в том, что аргумент to 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());