Java 8 пропонує новий спосіб виклику конструктора копій або методу клонування на елементах собак елегантно і компактно: Потоки , лямбда і колектори .
Конструктор копіювання:
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с
Колектор з останнього прикладу можна перетворити на утилітний метод. Оскільки це така звичайна річ, я особисто люблю, щоб вона була короткою і красивою. Подобається це:
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());