Mapuj kolekcję ogólną w Javie 11 [duplikat]
Próbowałem znaleźć sposób na napisanie funkcji ogólnej - być może bez użycia typów ogólnych - do mapowania kolekcji.
Powiedzmy, że mam funkcję od A do B, chciałbym napisać funkcję, która przyjmuje a Collection<A>
i zwraca a Collection<B>
. PAMIĘTAJ, że A i B nie są rodzajami, a jedynie sposobem wyrażenia ogólnego wzorca.
To, co mam do tej pory, to
public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(Collectors.toCollection(() -> points));
}
Jednak w tagu pojawia się błąd typu .collect
, ponieważ oczywiście chcę, aby nowa kolekcja była, Collection<Point>
ale nie jestem pewien, jak uzyskać do tego dostawcę?
Edycja: Chciałbym móc używać tej funkcji w sposób ogólny: jeśli przekażę jej zestaw, otrzymam w zamian zestaw, ale jeśli przekażę listę, otrzymam w zamian listę. czy jest to w ogóle możliwe?
Odpowiedzi
Najlepszą opcją jest unikanie nadmiernych komplikacji i po prostu:
public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(Collectors.toList());
}
zwracanie konkretnej implementacji interfejsu Collection
( np. Collectors.toList()
) z jednoczesnym ukryciem od zewnątrz szczegółów implementacji ( czyli posiadaniem Collection
w metodzie sygnatury).
Możesz jednak uczynić swoją metodę bardziej ogólną, przekazując do niej - jako Supplier
- konkretną implementację interfejsu, Collection
którą chcesz, aby zwracała, a mianowicie
public static Collection<Point> points2dToPoints(Collection<Point2D> points, Supplier<Collection<Point>> aNew) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(toCollection(aNew));
W ten sposób możesz przekazać konkretną Collection
implementację, która zostanie zwrócona, na przykład:
points2dToPoints(.., ArrayList::new);
points2dToPoints(.., TreeSet::new);
Wymień oświadczenie Collectors.toCollection(() -> points)
z Collectors.toList()
.
Próbny:
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
class Car {
String name;
public Car(String name) {
this.name = name;
}
@Override
public String toString() {
return "Car [name=" + name + "]";
}
}
class Book {
Car car;
public Book(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
}
public class Main {
public static void main(String[] args) {
// Test
Collection<Car> list = points2dToPoints(
List.of(new Book(new Car("Toyota")), new Book(new Car("Ford")), new Book(new Car("Suzuki"))));
list.forEach(System.out::println);
}
public static Collection<Car> points2dToPoints(Collection<Book> points) {
return points.stream().map(Book::getCar).collect(Collectors.toList());
}
}
Wynik:
Car [name=Toyota]
Car [name=Ford]
Car [name=Suzuki]