Reputation: 17727
I have a class Foo
for which I made an equivalence wrapper class WrappedFoo
to change its equals()
contract in some parts of the program.
I need to convert from Foo
objects to WrappedFoo
objects and vice versa in many places. But I also need to convert Collection
s of Foo
s and WrappedFoo
from one to another. Is there any way I can achieve this in a generic way?
Basically I want a method that like this:
public static Collection<WrappedFoo> wrapCollection(Collection<Foo> collection)
The problem is that I don't know what kind of Collection
implementation will be used and I wish to keep the same implementation for the resulting Collection
.
Upvotes: 5
Views: 1320
Reputation: 286
It's been a few years since this question was asked, but since java 1.8 you can use streams to achieve that:
public static Collection<WrappedFoo> wrapCollection(Collection<Foo> collection) {
List<WrappedFoo> wrappedList = collection.stream().map(m -> new WrappedFoo(m)).collect(Collectors.toList());
return new ApiBulkResponse<Wrapper>(wrappedList);
}
You'll just need to supply a constructor in your WrappedFoo
class to transform or encapsulate your Foo
object into a WrappedFoo
.
Upvotes: 0
Reputation: 29129
Perhaps Collections2.transform from the Google Guava libraries might provide the functionality you are looking for.
You should be able to pass a Function that wraps the Foo elements in WrappedFoo. The main question is whether it is acceptable for the new collection to be a view of the original collection (hence it will not have the same implementation as the original collection).
Upvotes: 1
Reputation: 68857
Using the Reflection API, you could do something like this (notice the 0
in the method name):
public static Collection<WrapperFoo> wrapCollection0(Collection<Foo> src)
{
try
{
Class<? extends Collection> clazz = src.getClass();
Collection dst = clazz.newInstance();
for (Foo foo : src)
{
dst.add(new WrapperFoo(foo));
}
return dst;
} catch(Exception e)
{
e.printStackTrace();
return null;
}
}
Now implement a whole bunch one-liner overload methods using the method above (notice the 0
in the calls):
public static ArrayList<WrapperFoo> wrapCollection(ArrayList<Foo> src)
{
return (ArrayList<WrapperFoo>) wrapCollection0(src);
}
public static Vector<WrapperFoo> wrapCollection(Vector<Foo> src)
{
return (Vector<WrapperFoo>) wrapCollection0(src);
}
...
Upvotes: 2
Reputation: 2930
The Collection-Interface guarantees the existence of the "boolean addAll(Collection c)"-method. I'd just try something along theese lines:
public static Collection<WrappedFoo> wrapFoos(Collection<Foo> col) {
Class<?> colClass = col.getClass();
Collection<WappedFoo> newCol = colClass.getConstructor().getInstance();
newCol.addAll(col);
return newCol;
}
Upvotes: 2