Cannot create an array of LinkedLists in Java...?

JavaArraysGenerics

Java Problem Overview


I'm working on a sparse matrix class that needs to use an array of LinkedList to store the values of a matrix. Each element of the array (i.e. each LinkedList) represents a row of the matrix. And, each element in the LinkedList array represents a column and the stored value.

In my class, I have a declaration of the array as:

private LinkedList<IntegerNode>[] myMatrix;

And, in my constructor for the SparseMatrix, I try to define:

myMatrix = new LinkedList<IntegerNode>[numRows];

The error I end up getting is

>Cannot create a generic array of LinkedList<IntegerNode>.

So, I have two issues with this:

  1. What am I doing wrong, and
  2. Why is the type acceptable in the declaration for the array if it can't be created?

IntegerNode is a class that I have created. And, all of my class files are packaged together.

Java Solutions


Solution 1 - Java

For some reason you have to cast the type and make the declaration like this:

myMatrix = (LinkedList<IntegerNode>[]) new LinkedList<?>[numRows];

Solution 2 - Java

You can't use generic array creation. It's a flaw/ feature of java generics.

The ways without warnings are:

  1. Using List of Lists instead of Array of Lists:

     List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
    
  2. Declaring the special class for Array of Lists:

     class IntegerNodeList {
         private final List< IntegerNode > nodes;
     }
    

Solution 3 - Java

Aside from the syntax issues, it seems strange to me to use an array and a linked list to represent a matrix. To be able to access arbitrary cells of the matrix, you would probably want an actual array or at least an ArrayList to hold the rows, as LinkedList must traverse the whole list from the first element to any particular element, an O(n) operation, as opposed to the much quicker O(1) with ArrayList or an actual array.

Since you mentioned this matrix is sparse, though, perhaps a better way to store the data is as a map of maps, where a key in the first map represents a row index, and its value is a row map whose keys are a column index, with the value being your IntegerNode class. Thus:

private Map<Integer, Map<Integer, IntegerNode>> myMatrix = new HashMap<Integer, Map<Integer, IntegerNode>>();

// access a matrix cell:
int rowIdx = 100;
int colIdx = 30;
Map<Integer, IntegerNode> row = myMatrix.get(rowIdx); // if null, create and add to matrix
IntegerNode node = row.get(colIdx); // possibly null

If you need to be able to traverse the matrix row by row, you can make the row map type a TreeMap, and same for traversing the columns in index order, but if you don't need those cases, HashMap is quicker than TreeMap. Helper methods to get and set an arbitrary cell, handling unset null values, would be useful, of course.

Solution 4 - Java

class IntegerNodeList extends LinkedList<IntegerNode> {}

IntegerNodeList[] myMatrix = new IntegerNodeList[numRows]; 

Solution 5 - Java

> myMatrix = (LinkedList<IntegerNode>[]) new LinkedList[numRows];

casting this way works but still leaves you with a nasty warning:

"Type safety: The expression of type List[] needs unchecked conversion.."

> Declaring a special class for Array of Lists: > > class IntegerNodeList { private final List< IntegerNode > nodes; }

is a clever idea to avoid the warning. maybe a little bit nicer is to use an interface for it:

public interface IntegerNodeList extends List<IntegerNode> {}

then

List<IntegerNode>[] myMatrix = new IntegerNodeList[numRows];

compiles without warnings.

doesn't look too bad, does it?

Solution 6 - Java

There is no generic array creation in Java 1.5 (or 1.6 as far as I can tell). See https://community.oracle.com/message/4829402.

Solution 7 - Java

List<String>[] lst = new List[2];
lst[0] = new LinkedList<String>();
lst[1] = new LinkedList<String>();

No any warnings. NetBeans 6.9.1, jdk1.6.0_24

Solution 8 - Java

If I do the following I get the error message in question

LinkedList<Node>[] matrix = new LinkedList<Node>[5];

But if I just remove the list type in the declaration it seems to have the desired functionality.

LinkedList<Node>[] matrix = new LinkedList[5];

Are these two declarations drastically different in a way of which I'm not aware?

EDIT

Ah, I think I've run into this issue now.

Iterating over the matrix and initializing the lists in a for-loop seems to work. Though it's not as ideal as some of the other solutions offered up.

for(int i=0; i < matrix.length; i++){
            
	matrix[i] = new LinkedList<>();
}

Solution 9 - Java

You need an array of List, one alternative is to try:

private IntegerNode[] node_array = new IntegerNode[sizeOfYourChoice];

Then node_array[i] stores the head(first) node of a ArrayList<IntegerNode> or LinkedList<IntegerNode> (whatever your favourite list implementation).

Under this design, you lose the random access method list.get(index), but then you could still traverse the list starting with the head/fist node store in the type safe array.

This might be an acceptable design choice depending on your use case. For instance, I use this design to represent an adjacency list of graph, in most use cases, it requires traversing the adjacency list anyway for a given vertex instead of random access some vertex in the list.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkafuchauView Question on Stackoverflow
Solution 1 - JavaFredrikView Answer on Stackoverflow
Solution 2 - JavaSergeyView Answer on Stackoverflow
Solution 3 - JavaDov WassermanView Answer on Stackoverflow
Solution 4 - JavaBobView Answer on Stackoverflow
Solution 5 - Javauser306708View Answer on Stackoverflow
Solution 6 - JavaPaul CroarkinView Answer on Stackoverflow
Solution 7 - JavaAndriiView Answer on Stackoverflow
Solution 8 - JavaRyanView Answer on Stackoverflow
Solution 9 - JavaYilingView Answer on Stackoverflow