¿No se puede crear una matriz de LinkedLists en Java …?

Estoy trabajando en una clase de matriz dispersa que necesita usar una matriz de LinkedList para almacenar los valores de una matriz. Cada elemento de la matriz (es decir, cada LinkedList ) representa una fila de la matriz. Y, cada elemento en la matriz LinkedList representa una columna y el valor almacenado.

En mi clase, tengo una statement de la matriz como:

 private LinkedList[] myMatrix; 

Y, en mi constructor para SparseMatrix , bash definir:

 myMatrix = new LinkedList[numRows]; 

El error que termino recibiendo es

No se puede crear una matriz genérica de LinkedList .

Entonces, tengo dos problemas con esto:

  1. ¿Qué estoy haciendo mal?
  2. ¿Por qué el tipo es aceptable en la statement de la matriz si no se puede crear?

IntegerNode es una clase que he creado. Y, todos mis archivos de clase están empaquetados juntos.

No puede usar la creación de matriz genérica. Es un defecto / característica de los generics de Java.

Las formas sin advertencias son:

  1. Usar la lista de listas en lugar de la matriz de listas:

     List< List> nodeLists = new LinkedList< List< IntegerNode >>(); 
  2. Declarando la clase especial para Array of Lists:

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

Por algún motivo, debe convertir el tipo y hacer la statement de esta manera:

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

Además de los problemas de syntax, me parece extraño usar una matriz y una lista vinculada para representar una matriz. Para poder acceder a las celdas arbitrarias de la matriz, es probable que desee una matriz real o al menos una ArrayList para contener las filas, ya que LinkedList debe atravesar toda la lista desde el primer elemento hasta cualquier elemento en particular, una operación O(n) , a diferencia del O(1) mucho más rápido con ArrayList o una matriz real.

Sin embargo, dado que mencionó que esta matriz es escasa, quizás una mejor forma de almacenar los datos es como un mapa de mapas, donde una clave en el primer mapa representa un índice de fila, y su valor es un mapa de fila cuyas claves son un índice de columna , con el valor siendo su clase IntegerNode. Así:

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

Si necesita poder recorrer la matriz fila por fila, puede hacer que el tipo de mapa de fila sea TreeMap , y lo mismo para recorrer las columnas en orden de índice, pero si no necesita esos casos, HashMap es más rápido que TreeMap . Los métodos de ayuda para obtener y establecer una celda arbitraria, manejando valores nulos sin establecer, serían útiles, por supuesto.

 class IntegerNodeList extends LinkedList {} IntegerNodeList[] myMatrix = new IntegerNodeList[numRows]; 

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

lanzar de esta manera funciona pero aún te deja con una desagradable advertencia:

“Tipo de seguridad: la expresión de tipo Lista [] necesita conversión sin marcar ..”

Declarando una clase especial para Array of Lists:

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

es una idea inteligente para evitar la advertencia. tal vez un poco mejor es usar una interfaz para ello:

 public interface IntegerNodeList extends List {} 

entonces

 List[] myMatrix = new IntegerNodeList[numRows]; 

comstack sin advertencias.

no se ve tan mal, ¿verdad?

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

No hay advertencias NetBeans 6.9.1, jdk1.6.0_24

No existe una creación de matriz genérica en Java 1.5 (o 1.6, por lo que puedo decir). Ver https://community.oracle.com/message/4829402 .

Si hago lo siguiente, recibo el mensaje de error en cuestión

 LinkedList[] matrix = new LinkedList[5]; 

Pero si elimino el tipo de lista en la statement, parece tener la funcionalidad deseada.

 LinkedList[] matrix = new LinkedList[5]; 

¿Son estas dos declaraciones drásticamente diferentes de una manera que no conozco?

EDITAR

Ah, creo que me he encontrado con este problema ahora.

Iterar sobre la matriz e inicializar las listas en un for-loop parece funcionar. Aunque no es tan ideal como algunas de las otras soluciones ofrecidas.

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

Necesita una matriz de Lista, una alternativa es intentar:

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

Entonces node_array[i] almacena el cabezal (primer) nodo de una ArrayList o LinkedList (cualquiera que sea su implementación de listas favoritas).

Con este diseño, se pierde el método de acceso aleatorio list.get(index) , pero aún se puede recorrer la lista comenzando con el almacén de nodos head / fist en el tipo safe array.

Esta podría ser una opción de diseño aceptable según su caso de uso. Por ejemplo, utilizo este diseño para representar una lista de adyacencia de gráfico, en la mayoría de los casos de uso, requiere atravesar la lista de adyacencia de todos modos para un vértice dado en lugar de acceder aleatoriamente a algún vértice en la lista.