Issue
I've been trying to find a way to write a generic function -- possibly not using generics -- to map over a collection.
Let's say I have a function A to B, I'd like to write a function that takes a Collection<A>
and returns a Collection<B>
. NOTE that A and B are not generics, just a way to express a general pattern.
What I have so far is
public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(Collectors.toCollection(() -> points));
}
However, I get a type error in the .collect
, because obviously I want the new collection to be Collection<Point>
but I'm not sure how to get a Supplier for that?
Edit: I would like to be able to use this function in a generic way: if I pass it a Set I get a Set in return, but if I pass it a List I get a list in return. is it even possible to do this?
Solution
The best option is to not overcomplicate, and simply do:
public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(Collectors.toList());
}
returning a concrete implement of interface Collection
(e.g., Collectors.toList()
) while hiding from the outside the implementation details, (i.e., having Collection
in the method signature).
You can, however, make your method more generic by passing to it -- as Supplier
-- which concrete implementation of the interface Collection
you want it to return, namely
public static Collection<Point> points2dToPoints(Collection<Point2D> points, Supplier<Collection<Point>> aNew) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(toCollection(aNew));
In this way you can pass the concrete Collection
implementation that will be returned, for example:
points2dToPoints(.., ArrayList::new);
points2dToPoints(.., TreeSet::new);
Answered By - dreamcrash
Answer Checked By - Timothy Miller (JavaFixing Admin)