How do I convert from List<?> to List<T> in Java using generics?

Derek Mahar :

In Java, how do I convert List<?> to List<T> using a general purpose method so that I can replace patterns like the following with a single method call:

List untypedList = new ArrayList();  // or returned from a legacy method
List<Integer> typedList = new ArrayList<Integer>();
for (Object item: untypedList)
    typedList.add((Integer)item);

Note that the above code does not generate any type-safety warnings and, ideally, your solution shouldn't generate any such warnings, either.

Will the following solution work provided that list Class<L> has a public default constructor?

public class ListUtil {
    public static <T, L extends List<T>> L typedList(List<?> untypedList, Class<T> itemClass, Class<L> listClass) {
        L list = null;
        try {
            list = listClass.newInstance();
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
        }
        for (Object item: untypedList)
            list.add(itemClass.cast(item));
        return list;
    }
}

(Note that listClass.newInstance() throws InstantiationException or IllegalAccessException if an instance of Class<L> does not have a public default constructor. What problems may arise if the method does not properly handle these exceptions?)

Notes:

  • T is the type of each item in the resulting list.
  • L is the type of the list that I wish to create (which extends List<T>).
  • untypedList is the "untyped" input list, effectively the same as List<Object>.
  • itemClass represents the runtime class of T.
  • listClass represents the runtime class of L.
Michael D :

Rather than passing in the type of the list you want to instantiate, why not just pass in the empty Collection<T> that you want populated? This gives the users of your api much more flexibility, as using the default constructor is not always ideal. (for example, maybe I want a Set where I provide the expected number of elements, or I want a sorted list where I provide the Comparator).

Also, as a side note, you should always program to the most generic interface possible. In this case, your input need be nothing more specific than an Iterable, and your output a Collection.

Given this, I would write the method this way --

  public static <T, C extends Collection<T>> C typesafeAdd(Iterable<?> from, C to, Class<T> listClass) {
    for (Object item: from) {
      to.add(listClass.cast(item));
    }
    return to;
  }

then the calling code looks like:

  public static void main(String[] args) {
    List<?> untypedStringList = LegacyApi.getStringList();
    List<String> typesafeStringList = typesafeAdd(untypedStringList, new ArrayList<String>(), String.class);
  }

2 Comments here:

  • If you can really trust LegacyApi (or whatever provided you the untyped List) to only return to you a collection with the expected type in it, then you can just do an unchecked cast and suppress it. This should be localized to the smallest scope possible. ie: create something like TypesafeLegacyApiWrapper which delegates calls to LegacyApi.
  • This method signature still breaks down if you have anything more complicated. For example if you have a List<List<String>> this method does not work.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to convert list without generics to list with generics using streams in java?

how to convert from a list of generics to list of objects in java 8?

How can I cast a list using generics in Java?

How do I convert a List<Employee> to Map<Employee, List<String>> using java8?

How do I batch-convert files from an input list using ImageMagick 'convert'?

cannot convert list to list error in java generics

Using Java 8 streams how do I convert Map<String, List<Something>> to Map<String, Integer>?

List of Generics T using Interface

How do I convert multiple lists inside a list using Python?

How do I convert a Python list into a C array by using ctypes?

How do I convert a list of Option<T> to a list of T when T cannot be copied?

Convert Map<String,List<Person>> to Map<String,List<Employee>>, using Java 8 streams. I did this but how do this without for loop

How do I convert httr response content from list to dataframe?

How do I convert java.sql.Array to List<MyCustomEnum>?

How do I convert a Java 8 IntStream to a List?

how i can convert from int[] to List<Integer> in java

How do I implement generics <E> in a linked List?

How can I use Java Generics to create a list of subclasses?

How do I keep java XMLEconder from using so much memory when writing a List?

How do I convert a list/dictionary into a Dataframe?

How do I convert a list of integers into bytes?

How do I convert a list into a matrix in KDB?

How do I convert list into dictionary in Python?

How do I convert a string to a list of chars?

How do I convert user input into a list?

How do I convert a list of tuples to a dictionary

How do I convert int(input) into a list

How do I convert an array or a list into a hashref?

How do I convert a Map in LIst to a Map?