qwertzguy
qwertzguy

Reputation: 17727

How to wrap each object of a Collection in Java?

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 Collections of Foos 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

Answers (4)

marcel
marcel

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

Mark
Mark

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

Martijn Courteaux
Martijn Courteaux

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

TreffnonX
TreffnonX

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

Related Questions