I encountered a problem while solving problems on LeetCode. The question has a form:
public List<List<Integer>> generate(){
}
that requires returning a List<List<Integer>>. I know for List<T> I can do a LinkedList<T> or ArrayList<T>. How can I instantiate it that the compiler would not complain? Thanks
return new ArrayList<List<Integer>>();
The outer list type needs to be a concrete type like ArrayList or LinkedList, but the inner list type should be List. On more recent Java versions, you can do
return new ArrayList<>();
List<List<Integer>> myList = new ArrayList<List<Integer>>();
Then when you want to add stuff to it do
List<Integer> innerList = new ArrayList<Integer>(); myList.add(innerList);
Related
I have a function that returns a list of lists of integers
public List<List<Integer>> threeSum(int[] nums)
Obviously I can't directly instantiate a List so I chose to use an ArrayList and tried to instantiate my return value as such:
List<List<Integer>> ans = new ArrayList<ArrayList<Integer>>();
The above did not work but this did:
List<List<Integer>> ans = new ArrayList<List<Integer>>();
My understanding is that List is an interface that ArrayList inherits from. Why, then, can I instantiate an ArrayList of Lists and be ok but I can't instantiate an ArrayList of ArrayLists?
For readability the first few lines of my function look as such:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
if (nums.length < 3) return ans;
This is because an ArrayList<ArrayList<Integer>> is NOT a List<List<Integer>>.
The reason is that a List<List<Integer>> is something that you should be able to add a LinkedList<Integer> to. But you can't add a LinkedList<Integer> to an ArrayList<ArrayList<Integer>> because it's the wrong type.
Therefore, if you've got an ArrayList<ArrayList<Integer>>, you can never treat it as a List<List<Integer>>, or reference it with a variable of type List<List<Integer>>
but I can't instantiate an ArrayList of ArrayLists?
because you specified type of ans as List of Lists not List of ArrayLists.
List<List<Integer>> ans = new ArrayList<ArrayList<Integer>>();
The above did not work
I guess it will work if declaration will be:
List<? extends List<Integer>> ans = new ArrayList<ArrayList<Integer>>();
This is Java Generics. List<List<Integer>> ans = new ArrayList<ArrayList<Integer>>() does not work because the outer list expects itself to keep List<Integer>, not ArrayList<Integer>.
Consider this:
List<Number> list = new ArrayList<Integer>();
This does not work either, because the list expects Number, not Integer.
Anyway when nesting lists, you need to instantiate inner lists as well. Lists of Lists do not work like multidimensional arrays.
While defining a 2D dynamic array why can't I define it like this:
List<List<Integer>> t=new List<List<Integer>();
On doing so, I got an error saying:
Cannot instantiate the type List<List<Integer>>
I came to know that this is the best practice for it-
List<List<Integer>> t=new Arraylist<List<Integer>>();
why is it so.can someone help me understand this.
List is an interface an as such can not use new to create a new instance of it, you need classes that implement it instead eg ArrayList
List<List<Integer>> t=new ArrayList<List<Integer>>();
or since java 7
List<List<Integer>> t = new ArrayList<>();
Because in Java, List is an Interface you can't initialize it.
You can do it like that;
List<t> list = new ArrayList<t>();
Just initialize any types that implement the List Interface
This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 5 years ago.
In Java, why doesn't the following line of code work?
List<List<String>> myList = new ArrayList<ArrayList<String>>();
It works if I change it to
List<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();
At first, I thought maybe you can't have lists of an interface, but I can create a List<Runnable> just fine.
Ideas?
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
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 :-) )
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);
Its comparing Type from left(declaration) side to Type from right(instantiation) side. In Left, your type is List<String> while in right, it's ArrayList<String>. If complaining about the difference.
Please update the right side(instatiation) as List i.e.
List<List<String>> myList = new ArrayList<List<String>>();
This should work fine.
I know this is an old question but I just wanted to share my idea.
Instead of making a List of Lists, I personally just make a List of Type[] (List<Type[]> listArray = new ArrayList<Type[]>();), I generate a separate List of just Type (List<Type> list = new ArrayList<Type>();), then .add(list.toArray()). This way, it's clearer and easier to read than the List of Lists syntax which is confusing.
For example, in a recent project where I had an input file where each line with only a "0" meant a new line in the original (it was an encryption algorithm):
String[] input = getInputContents(inFile);
List<String> currentBuffer = new ArrayList<String>();
List<String[]> buffers = new ArrayList<String[]>();
for(String line : input) {
if(line.equals("0")) {
buffers.add((String[])currentBuffer.toArray());
currentBuffer = new ArrayList<String>();
} else {
currentBuffer.add(line);
}
}
the list<list<string>> l1=new list<list<string>>(); is allowed if the list contains one more list inside the list.
public final class CPanelXMLBuilder extends PanelXMLBuilder {
public CPanelXMLBuilder(AuthenticatedUser pAuthenticatedUser, Map<String, Object> pSessionMap, Map<String, Object> pRequestMap, String pPanelTemplate) throws Exception {
super(pAuthenticatedUser, pSessionMap, pRequestMap, pPanelTemplate, null);
}
public Map<String, Object> buildXMLDocument(List<List<String>> pDetailsList) {
if (pDetailsList.size() == 1) {
List<String> pCustomerDetail = pDetailsList.get(0);
xmlDocument.getRootElement().getChild("E_SHOW1").setText(pCustomerDetail.get(0));
xmlDocument.getRootElement().getChild("E_SHOW2").setText(pCustomerDetail.get(1));
xmlDocument.getRootElement().getChild("E_SHOW3").setText(pCustomerDetail.get(2));
xmlDocument.getRootElement().getChild("E_SHOW4").setText(pCustomerDetail.get(3));
xmlDocument.getRootElement().getChild("E_SHOW5").setText(pCustomerDetail.get(4));
xmlDocument.getRootElement().getChild("ServerTimestamp").setText(pCustomerDetail.get(5).substring(0, 19));
} else {
xmlDocument.getRootElement().getChild("AlertType").setText("INFO");
xmlDocument.getRootElement().getChild("Alert").setText("There is no matching record.");
}
requestMap.put(RequestMapKeys.XML_DOCUMENT, xmlDocument);
return requestMap;
}
}
Can a List<T> be initialized to contain a given number of nulls, where T is a type parameter of the class of which the list is a member? I sure can do it with a loop, but like to know whether it is possible without.
List<T> myList = new ArrayList<T>(numEls);
creates a list of the given capacity, but size 0, so myList.get(x) fails for all x, and so does, e.g. myList.set(numEls-1,null).
myList = Arrays.asList(new T[numEls]);
does not compile, and
myList = (List<T>) Arrays.asList(new Object[numEls]);
compiles in Eclipse (with an Unchecked cast warning), but not with javac.
Update: Thank you for the answers! However, I found another, quite short, solution close to my last attempt above, which compiles both in eclipse and with our automated build system: Cast the array, not the list!
myList = Arrays.asList((T[]) new Object[numEls]);
If you don't need to mutate the list...
List<T> result = Collections.nCopies(num, (T) null);
... or alternately
List<T> result = new ArrayList<T>(Collections.nCopies(num, (T) null));
You would need to use reflection to instantiate a backing array T[] using Array.newInstance():
public static <T> List<T> getListWithNulls(Class<T> componentType, int length) {
T[] array = (T[])Array.newInstance(componentType, length);
return new ArrayList<T>(Arrays.asList(array));
}
As you can see, this requires a reference to the Class<T> object representing the type of T:
List<String> strListWithNulls = getListWithNulls(String.class, 100);
Also make sure not to confuse the classes java.lang.reflect.Array and java.util.Arrays which are both used here.
Finally, note that reflection is going to be much slower than just using a loop.
Not really a solution, but you wanted to avoid a loop.
void fillNullList(List<T> list, count) {
if (count > 0) {
list.add(null);
fillNullList(list, count - 1);
}
}
Seriously, why do you want to avoid a loop? Probably, you want a solution with O(1) complexity and not a O(n) complexity solution regardless if a loop is used for not.
What you probably want is something like this....
final int maxSize = 50;
List<T> v = new Vector<T>() {{setSize(maxSize);}};
Vectors allow you to set a size, which fills them with null's.
I would just use a loop, its simpler and likely to be faster as well.
List<T> list =
while(list.size()<size) list.add(null);
Any other approach you use is likely to use a loop for you. If this is fine, just write your own method which hides the loop used.
new option with streams:
List resultColumn = IntStream.range(0, 10000).mapToObj(i -> null).collect(Collectors.toList());
Try this:
List<String> list = new ArrayList<String>(Arrays.asList(new String[100]));
for(String string : list){
System.out.println(string);
}
Well, you can write a hierarchy:
class Base<T>{
protected List<T> list;
public List<T> getList(){
return list;
}
}
class Child extends Base<String>{
public Child(){
list = new ArrayList<String>(Arrays.asList(new String[100]));
}
}
It can be used in the next way:
Base<String> base = new Child();
base.getList();
What I did was
MyClass[] array = {new MyClass(), new MyClass(), new MyClass(), new MyClass(), new ProfileSectionDTO(), new MyClass()};
List<MyClass> MyClassList = Arrays.asList(array);
Dirty, but working :)
if you want an ArrayList you can use reflection to cheat
ArrayList<T> myList = new ArrayList<T>(numEls);
Field f = ArrayList.class.getField("size");//cache this
f.setAccessible(true);
f.setInt(myList, numEls);
I try use List instead of List
List<?> list = new ArrayList<Integer>();
...
list.add(1); //compile error
What i do wrong and how cast new value to Integer?
Maybe i shoud use List in my project?
List<?> means a list of some type, but we don't know which type. You can only put objects of the right type into a list - but since you don't know the type, you in effect can't put anything in such a list (other than null).
There is no way around this, other than declaring your variable as List<Integer>.
List<Integer> list = new ArrayList<Integer>();
The generic type always has to be the same.
List<Integer> list = new ArrayList<Integer>();
...
list.add(1);
List<?> list = new ArrayList<Integer>();
? means some type, you have to specify the Type as Integer. so the correct syntax would be :
List<Integer> list = new ArrayList<Integer>();