Java Collection<Object> or Collection<?> - java

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>();

Related

How to Use An Objects getClass() Method to set a generic type

Please a take look at example code below:
Object o1= new Integer(4);
ArrayList<Integer> list=new ArrayList<>();
list.add((Integer) o1);
Instead I'd Like to do something like:
Object o1= new Integer(4);
ArrayList<o1.getClass().getSimpleName()> list=new ArrayList<>();
list.add((o1.getClass().getSimpleName()) o1);
o1.getClass().getSimpleName() returns "Integer" as a Java.lang.String object, my question is how can I embed this string into my code some how with reflection so the type of items in list can be determined at runtime.
It is possible to do so by switch statement like:
Object o1= new Integer(4);
switch(o1.getClass().getSimpleName()){
case "Integer":
ArrayList<Integer> list=new ArrayList<>();
list.add((Integer) o1);
case "String":
/* some code */
}
but I hope there will be a better solution.
It is not possible due to type erasure. What you can do though is to have a list like this:
List<Object> list = new ArrayList<>();
list.add(12);
list.add("String");
So this way you can have whatever object you want in your list
As #Mibac said, you can't create list this way.
What you can do is somekind of "casting" using Stream API, if you are 100% sure that all objects int your list are of the same type:
Object o1 = new Integer(2);
List<Object> someList = new ArrayList<>();
someList.add(o1);
List<Integer> anotherList = new ArrayList<>();
anotherList.addAll(someList.stream().map(o -> (Integer) o).collect(Collectors.toList()));
System.out.println(anotherList);

One Iterator Different Types of LinkedList

I am still learning about Iterators and they are so much fun. However I have a question:
I made two DoubleLinkedList each with a different generic <Type>. I want to iterate through each one using only one Iterator, how can I change the generic <> on my Iterator?
DLL<String> aList = new DLL<>();
DLL<Integer> bList = new DLL<>();
DLL<String>.MyIterator<String> it = aList.Iterator();
With "it" iterator I can only iterate through aList but not bList.
it = new bList.Iterator();
This code doesn't help because it still thinks it's working with Strings.
I'm not familiar with your DLL or DoubleLinkedList class, but I think this is not important and confuses the issue. This is my answer using a simple java.util.List.
If you really must use the same Iterator variable, use the generic wildcard <?>. However, be aware that you will have to cast your object, just like in pre-generics Java:
List<String> stringList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
Iterator<?> it = stringList.iterator();
String string = (String) it.next();
it = intList.iterator();
Integer integer = (Integer) it.next();

Creating a new ArrayList

i have a question about creating a new array list.
If i create a new one, with
ArrayList <?> listtwo = new ArrayList<?>();
What can i put into the array? Can i put Strings and Integers in it?
Or how does this work.
I know that if you create an list like :
ArrayList<String> list =new ArrayList<String>();
that you can only put Strings in it. and if u try to do something else it gives a compile exception.
If i create a new one, with
ArrayList <?> listtwo = new ArrayList<?>();
You can't. You can't instantiate a parameterized type without bounds. Here's what the compiler will say:
ArrayList <?> listtwo = new ArrayList<?>();
^
required: class or interface without bounds
found: ?
So the question of what you can put in it is moot.
If you didn't supply a type parameter at all:
ArrayList listtwo = new ArrayList();
...you could put anything you liked into it (including a mix of things). Primitive values will get coerced to their object equivalents (int => Integer, etc.). At that point, it's basically an ArrayList<Object> instance.
There are two issues here.
(a) new ArrayList<?> is not a legal expression.
If you want to create a list that can hold String and Integers you need to use ArrayList<Object> as Object is the (most specific) common super-type of String and Integer:
ArrayList<Object> list = new ArrayList<Object>;
list.add('abcd'); // insert a string
list.add(1234); // insert an integer
The down side is that when you extract an item from this list it will be of type Object so you will need to downcast it:
String s = (String) list.get(0);
Integer n = (Integet) list.get(1);
(b) Regarding the wildcard ? symbol:
It can be used for specifying the type of a variable, as in: ArrayList<?> list = ... but it cannot be used in a new expression. In other words, this expression is illegal: new ArrayList<?>.
The wildcard is useful for allowing (limited) polymorphism between lists. Specifically, if you have a List of Integers and you want to treat it like a list of Number (which makes sense as Integer is a subclass of Number) you can use the wildcard symbol.
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(100);
list2.add(200);
// This assignment is OK:
ArrayList<? extends Number> list3 = list2;
Number n = list3.get(0); // n is now 100
However, the problem with list3 (or any other list with a wildcard type) is that you cannot mutate it. For instance, if you try to add an element to this list:
list3.add(300); // <-- This is not allowed
you will get a compile-time error.

How to instantiate a List<List<Integer>>?

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);

How can I get to the particular element in the list which is internal list of other list in Java?

If I declare something like this:
List<Object> list = new ArrayList<Object>();
list.add(new ArrayList<String>());
list.get(0).get(1);//error
Now I have got "list in list" and I would like to get to the second element of the internal list of the first list. How can I do that? This doesn't work:
list.get(0).get(1);//error
You need to cast the returned object from list to ArrayList, since you declared your list with Object type > List<Object>
So try to change your code to something like:
((ArrayList<String>) list.get(0)).get(1);
Or change the declaration of your list like:
List<List<String>> list = new ArrayList<List<String>>();
Then your code should work fine.
Why not declare this properly ?
List<List<String>> list = new ArrayList<List<String>>();
list.add(new ArrayList<String>());
i.e. you declare this as a list of lists, and the compiler knows that list.get(0) will give you a list.

Categories