tags:

views:

7814

answers:

6

I'm working on a sparse matrix class that needs to use an array of LinkedLists 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 LinkedLists 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?

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

+27  A: 

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

myMatrix = (LinkedList<IntegerNode>[]) new LinkedList[numRows];
ique
This would work too. Thanks.
kchau
I researched a similar problem and read that the above cast is a very common 'hack' that is used all over the collections framework.
luke
IMO, this should be the selected answer. I haven't experimented, but I have the gut feeling that Sergey's #2 method creates quite a bit of overhead; and I'm POSITIVE that #1 does. A list is not as efficient as an array in several ways which I won't detail here, but I HAVE done experiments and seen big slowdowns when using lists compared to arrays. It's faster to just manage your own arrays and reallocate them, than to add stuff to a List.
Ricket
+2  A: 

There is no generic array creation in Java 1.5 (or 1.6 as far as I can tell). See http://forums.sun.com/thread.jspa?threadID=530823.

Paul Croarkin
+13  A: 

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;
    }
    
Sergey
A better alternative to the latter solution would be to:`class IntegerNodeList extends List<IntegerNode> {}`
msakr
+3  A: 

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.

Dov Wasserman
+1  A: 

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?

IntegerNodeList: what class would you use this with? For instance you could not assign an ArrayList <IntegerNode> to it. You would need to extend ArrayList as well...
hstoerr
there is no need to use the interface IntegerNodeList outside the initialization of the array: List<IntegerNode>[] myMatrix = new IntegerNodeList[5]; for (int i = 0; i < myMatrix.length; i++) { myMatrix[i] = new ArrayList<IntegerNode>(); }
A: 

myMatrix = (LinkedList[]) new LinkedList[numRows];

This solution gives me a null pointer Exception

LinkedList<String>[] array = (LinkedList<String>[]) new LinkedList[6];
     array[0].add("Ahmed");
Ahmed Hamdy
I know why the error happened.Sorry for that :)I forgot to initialize The array of LinkedList with new Linkedlist'for(int i=0; i<array.length; i++) array[i] = new LinkedList<String>;'
Ahmed Hamdy