Mapa sobre colección genérica en Java 11 [duplicado]
He estado tratando de encontrar una manera de escribir una función genérica, posiblemente sin usar genéricos, para mapear una colección.
Digamos que tengo una función A a B, me gustaría escribir una función que tome Collection<A>ay devuelva a Collection<B>. TENGA EN CUENTA que A y B no son genéricos, solo una forma de expresar un patrón general.
Lo que tengo hasta ahora es
public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(Collectors.toCollection(() -> points));
}
Sin embargo, obtengo un error de tipo en el .collect, porque obviamente quiero que sea la nueva colección, Collection<Point>pero no estoy seguro de cómo obtener un Proveedor para eso.
Editar: Me gustaría poder usar esta función de forma genérica: si le paso un Conjunto, obtengo un Conjunto a cambio, pero si le paso una Lista, obtengo una lista a cambio. ¿Es posible hacer esto?
Respuestas
La mejor opción es no complicar demasiado y simplemente hacer:
public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(Collectors.toList());
}
devolver un implemento concreto de interfaz Collection( por ejemplo, Collectors.toList() ) mientras se oculta del exterior los detalles de implementación ( es decir, tener Collectionen la firma del método).
Sin embargo, puede hacer que su método sea más genérico pasándole, como Supplier, qué implementación concreta de la interfaz Collectiondesea que devuelva, es decir
public static Collection<Point> points2dToPoints(Collection<Point2D> points, Supplier<Collection<Point>> aNew) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(toCollection(aNew));
De esta forma se puede pasar la Collectionimplementación concreta que se devolverá, por ejemplo:
points2dToPoints(.., ArrayList::new);
points2dToPoints(.., TreeSet::new);
Reemplace la declaración Collectors.toCollection(() -> points)con Collectors.toList().
Manifestación:
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());
}
}
Salida:
Car [name=Toyota]
Car [name=Ford]
Car [name=Suzuki]