Why can't you have a "List<List<String>>" in Java? [duplicate]
Solution 1:
Generic types are more pedantic.
List
means List
or any sub-type, but <List>
means only List
. If you want a sub-type you need to have <? extends List>
I suspect you can use
List<List<String>> myList = new ArrayList<List<String>>();
The reason you can't do this is that you can be using a reference to a reference and with an extra level of indirection you have to be careful.
// with one level of indirection its simple.
ArrayList alist = new ArrayList();
List list = aList; // all good
list = new LinkedList(); // alist is still good.
With generics you can have two level of indirection which can give you problems so they are more pedantic to avoid these issues.
// with two levels of indirection
List<ArrayList> alist = new ArrayList<ArrayList>();
List<List> list = (List) alist; // gives you a warning.
list.add(new LinkedList()); // adding a LinkedList into a list of ArrayList!!
System.out.println(alist.get(0)); // runtime error
prints
Exception in thread "main" java.lang.ClassCastException: java.util.LinkedList
cannot be cast to java.util.ArrayList
Solution 2:
Lets start with this:
ArrayList<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();
This is creating an ArrayList whose elements are ArrayLists.
Now suppose we could assign that to
List<List<String>> myList2 = myList.
Now, we should be able to do this:
myList2.add(new LinkedList<String>());
But that means we have added a LinkedList to a list whose elements are supposed to be ArrayLists. Ooops!!!
In reality, the assignment of myList
to myList2
is not legal ... and that ensures that it is not possible to add the wrong kind of List<String>
to the ArrayList<ArrayList<String>>
object. (No Peter, it is not just pedantry :-) )
Solution 3:
Only the top level collection can be declared as an implementing class, while the nested ones must remain interfaces until you actually create instances:
List<List<String>> rootList = new ArrayList<List<String>>();
and then when you create an element to go in, you make it an implementation:
List<String> nodeList = new ArrayList<String>();
rootList.add(nodeList);