Java 1.6: Creating an array of ListT
Well, generics tutorial give the answer to your question.
The component type of an array object
may not be a type variable or a
parameterized type, unless it is an
(unbounded) wildcard type.You can
declare array types whose element type
is a type variable or a parameterized
type, but not array objects.This is
annoying, to be sure. This restriction
is necessary to avoid situations like:// Not really allowed.
List<String>[] lsa = new List<String>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Unsound, but passes run time store check
oa[1] = li;
// Run-time error: ClassCastException.
String s = lsa[1].get(0);
If arrays of parameterized type were
allowed, the previous example would
compile without any unchecked
warnings, and yet fail at run-time.
We've had type-safety as a primary
design goal of generics.
Create ArrayList from array
new ArrayList<>(Arrays.asList(array));
Specific Java generic array creation
I don't think you can create an array of generics.
Check this out. Java 1.6: Creating an array of List<T>
This is because the type information isn't available at runtime.
How to properly define an array of linked list in Java ?
This is a proper way to create an array:
@SuppressWarnings("unchecked") LinkedList<Long> [] hashtable = new LinkedList[10];
Cannot Create Arrays of Parameterized Types
You cannot create arrays of parameterized types. For example, the following code does not compile:
List<Integer>[] arrayOfLists = new List<Integer>[2]; // compile-time error
The following code illustrates what happens when different types are inserted into an array:
Object[] strings = new String[2];
strings[0] = "hi"; // OK
strings[1] = 100; // An ArrayStoreException is thrown.
If you try the same thing with a generic list, there would be a problem:
Object[] stringLists = new List<String>[]; // compiler error, but pretend it's allowed
stringLists[0] = new ArrayList<String>(); // OK
stringLists[1] = new ArrayList<Integer>(); // An ArrayStoreException should be thrown,
// but the runtime can't detect it.
If arrays of parameterized lists were allowed, the previous code would fail to throw the desired ArrayStoreException
.
Taken from docs.oracle.com
So what can I store in hashtable[] ?
Does it mean I am now allowed to have a linked list of string in the
hashtable[0] and a linked list of Long in hashtable1, if I do
LinkedList [] hashtable = new LinkedList[10]?
No, compiler won't allow you to store LinkedList to the hashtable array directly. Following snippet won't compile:
hashtable[0] = new LinkedList<String>();
However you can store the LinkedList without type parameters, or even a subclass of LinkedList:
@SuppressWarnings("unchecked") LinkedList<Long>[] hashtable = new LinkedList[10];
hashtable[0] = new LinkedList<Long>();
hashtable[1] = new MyLinkedList<Long>();
hashtable[2] = new LinkedList();
hashtable[3] = new MyLinkedList();
You can store the LinkedList if you cast your array to LinkedList[]. However you won't be able to store the anything else but a LinkedList:
LinkedList[] rawHashTable = hashtable;
rawHashTable[4] = new LinkedList<String>();
Object[] objectHashTable = rawHashTable;
objectHashTable[5] = "This line will throw an ArrayStoreException ";
Array of Linked Lists Java
It’s not as straightforward as it sounds, but yes, you can use java.util.LinkedList
.
It requires that you declare your array an array of LinkedList
or just List
(not an array of String
). This works:
List<String>[] array = new List[1000];
for (int i = 0; i < array.length; i++){
array[i] = new LinkedList<>();
}
However, where I instantiate the array, I get a warning: Type safety: The expression of type List[] needs unchecked conversion to conform to List<String>[]
. One would have expected new List<String>[1000]
to work, but it doesn’t. It gives an error: Cannot create a generic array of List<String>
. The element type of an array cannot be a generic type. It’s a peculiarity with historic reasons, we’ll just have to live with it.
Creating an array to store generic types in Java
Question 1:
Basically, this is forbidden by Java language. This is covered in Java Language Specification for generics.
When you use
ArrayList<Integer>[] pl2 = new ArrayList[10]; // warning
you get the compiler warning, because the following example will compile (generating warning for every line of code):
ArrayList wrongRawArrayList = new ArrayList(); // warning
wrongRawArrayList.add("string1"); // warning
wrongRawArrayList.add("string2"); // warning
pl2[0] = wrongRawArrayList; // warning
but now you array, that supposed to contain ArrayList
of Integer
, contains totally wrong ArrayList
of String
objects.
Question 2:
As it was already answered, declaration of p12
provides you with compile time checking and frees you from using casting when getting items from your ArrayList
.
Slightly modified previous example:
ArrayList<Integer>[] pl2 = new ArrayList[10]; // warning
ArrayList<String> wrongArrayList = new ArrayList<String>(); // OK!
wrongArrayList.add("string1"); // OK!
wrongArrayList.add("string2"); // OK!
pl2[0] = wrongArrayList; // ERROR
Now, since you are using generics, this won't compile.
But if you use
ArrayList[] pl2 = new ArrayList[10];
you will get the same result as in the first example.
How to create a generic array in Java?
I have to ask a question in return: is your GenSet
"checked" or "unchecked"?
What does that mean?
Checked: strong typing.
GenSet
knows explicitly what type of objects it contains (i.e. its constructor was explicitly called with aClass<E>
argument, and methods will throw an exception when they are passed arguments that are not of typeE
. SeeCollections.checkedCollection
.-> in that case, you should write:
public class GenSet<E> {
private E[] a;
public GenSet(Class<E> c, int s) {
// Use Array native method to create array
// of a type only known at run time
@SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, s);
this.a = a;
}
E get(int i) {
return a[i];
}
}Unchecked: weak typing. No type checking is actually done on any of the objects passed as argument.
-> in that case, you should write
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
a = new Object[s];
}
E get(int i) {
@SuppressWarnings("unchecked")
final E e = (E) a[i];
return e;
}
}Note that the component type of the array should be the erasure of the type parameter:
public class GenSet<E extends Foo> { // E has an upper bound of Foo
private Foo[] a; // E erases to Foo, so use Foo[]
public GenSet(int s) {
a = new Foo[s];
}
...
}
All of this results from a known, and deliberate, weakness of generics in Java: it was implemented using erasure, so "generic" classes don't know what type argument they were created with at run time, and therefore can not provide type-safety unless some explicit mechanism (type-checking) is implemented.
Related Topics
Platform Independent Paths in Java
Converting an Array of Objects to an Array of Their Primitive Types
Jtable Disable Checkbox in Cell
Should I Use Java's String.Format() If Performance Is Important
Declaring an Unsigned Int in Java
How to Remove Single Character from a String
What Objects How to Inject Using the @Context Annotation
Write a File in Hdfs with Java
Reverse Each Individual Word of "Hello World" String with Java
What Are the Differences Between Arraylist and Vector
How to Asynchronously Call a Method in Java
Java: Why Is the Date Constructor Deprecated, and What Do I Use Instead
Configure Hibernate (Using JPA) to Store Y/N for Type Boolean Instead of 0/1
Using Hibernate's Scrollableresults to Slowly Read 90 Million Records
Why Does My Sorting Loop Seem to Append an Element Where It Shouldn'T