Search code examples
javagenericsgeneric-programminggeneric-collections

What signature should a generic method in Java have so that It can accept any <T that implements Iteralbe and stores List<U>> and...?


I want to create a method that traverses through any collection that stores ArrayList<U> - let's call that collection T; for example, it can be LinkedList, ArrayList or any other Collection; U - is another type which is needed to be memorized; and the method I want to create should return the same collection T but it should store LinkedList<U> instead.

"Wrong" desired declaration:

public <T extends Collection, U> T<LinkedList<U>> rewrap (T<ArrayList<U>> arrayList) {
    T<LinkedList<U>> linkedList = new T<LinkedList<U>>();
    // do some stuff here
    return linkedList;
}

I carefully read the documentation but I didn't find the way how I can achieve my goal.


Solution

  • My suggestion:

    public static <T, C extends Collection<LinkedList<T>>> C rewrap (Collection<ArrayList<T>> in, Supplier<C> collectionFactory) {
    
        C out = collectionFactory.get ();
    
        for (ArrayList<T> list : in) {
          out.add (new LinkedList<T> (list));
        }
    
        return out;
    }
    

    Note that you must pass a Supplier in order for the method to be able to create an instance of the Collection of the desired type.

    Usage:

    ArrayList<ArrayList<String>> in = new ArrayList<> ();
    in.add (new ArrayList<String> ());
    in.get (0).add ("abc");
    ArrayList<LinkedList<String>> out = rewrap (in, ArrayList::new);
    

    EDIT: You should note that this method doesn't require that the type of the output outer Collection is the same as the type of the input outer Collection.

    For example, you can pass an ArrayList<ArrayList<String>> input and get a HashSet<LinkedList<String>> output if you pass a HashSet::new supplier instead of ArrayList::new in the above example.