2008-10-19 26 views
96

Estoy trabajando en una clase de matriz dispersa que necesita para 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.¿No se puede crear una matriz de LinkedLists en Java ...?

En mi clase, tengo una declaración de la matriz como:

private LinkedList<IntegerNode>[] myMatrix; 

Y, en mi constructor para la SparseMatrix, trato de definir:

myMatrix = new LinkedList<IntegerNode>[numRows]; 

El error termino consiguiendo es

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

lo tanto, tengo dos problemas con esto:

  1. ¿Qué estoy haciendo mal, y
  2. ¿Por qué es el tipo aceptable en la declaración de la matriz si no puede ser creado?

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

Respuesta

63

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

Las formas sin advertencias son:

  1. Uso de la lista de las listas en lugar de la matriz de Listas:

    List< List<IntegerNode>> nodeLists = new LinkedList< List<IntegerNode>>(); 
    
  2. Declaración de la clase especial para Arsenal de Listas:

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

Una mejor alternativa a esta última solución sería: IntegerNodeList 'clase extiende Lista {}' – kamasheto

+5

lo anterior tendría que ser una implementación de la lista es decir, se extiende ArrayList .... – Dori

+0

Esta aplicación es exageradamente lento. Obtener el elemento [1000] [2000] (nodeLists.get (1000) .get (2000)) hará que LinkedList itere 3000 veces. Evite LinkedList si alguien puede indexarlo. ArrayList se indexará más rápido, pero la solución de Fredrik es mejor en general. –

133

Por alguna razón usted tiene que emitir el tipo y hacer la declaración de esta manera:

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

Investigué un problema similar y leí que el reparto anterior es un 'hack' muy común que se usa en todo el marco de colecciones. – luke

+15

IMO, esta debería ser la respuesta seleccionada. No he experimentado, pero tengo la corazonada de que el método # 2 de Sergey crea bastante sobrecarga; y soy POSITIVO que el # 1 lo hace. Una lista no es tan eficiente como una matriz de varias maneras que no detallaré aquí, pero HAGO experimentos y he visto grandes ralentizaciones al usar listas en comparación con las matrices. Es más rápido administrar sus propias matrices y reasignarlas que agregar cosas a una lista. – Ricket

+0

@Ricket Acepto, tomado de http://www.ibm.com/developerworks/java/library/j-jtp01255/index.html – Peteter

5

Aparte f En cuanto a los problemas de sintaxis, me parece extraño utilizar una matriz y una lista vinculada para representar una matriz. Para poder acceder a las celdas arbitrarias de la matriz, probablemente desee una matriz real o al menos un 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), en oposición a la mucho más rápida O(1) con ArrayList o una matriz real. Como mencionó 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 de su clase IntegerNode.Por lo tanto:

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 

Si tiene que ser capaz de atravesar la matriz fila por fila, puede hacer que el mapa fila escriba un TreeMap, y lo mismo para atravesar las columnas en el orden del índice, pero si no es necesario 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.

3

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

fundición de esta manera los trabajos, pero todavía le deja con una advertencia desagradable:

"seguridad Tipo: La expresión de tipo List [] necesidades de conversión sin control .."

Declarando una clase especial para Matriz de Listas:

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

es una buena idea para evitar la advertencia. tal vez un poco mejor es utilizar una interfaz para que:

public interface IntegerNodeList extends List<IntegerNode> {} 

continuación

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

compila sin advertencias.

no se ve tan mal, ¿o sí?

+0

IntegerNodeList: ¿con qué clase usarías esto? Por ejemplo, no puede asignarle una ArrayList . Necesitará extender ArrayList también ... –

+0

no es necesario utilizar la interfaz IntegerNodeList fuera de la inicialización de la matriz: Lista [] myMatrix = new IntegerNodeList [5]; for (int i = 0; i (); } – user306708

+1

'List [] myMatrix = new IntegerNodeList [numRows];' Esto tiene un problema sutil pero importante. Puede * solo * poner 'IntegerNodeList' en la matriz. 'myMatrix [i] = new ArrayList ();' lanzará 'ArrayStoreException'. – Radiodef

4
class IntegerNodeList extends LinkedList<IntegerNode> {} 

IntegerNodeList[] myMatrix = new IntegerNodeList[numRows]; 
+0

Te perdiste los genéricos de LinkedList. –

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

No hay ninguna advertencia. NetBeans 6.9.1, jdk1.6.0_24

+0

Verdadero no hay advertencias, pero con Java SE 6 Update 32 de Oracle me sale el error de compilación "El tipo List no es genérico, no se puede parametrizar con argumentos ". Al eliminar el argumento , se genera otro error "No coincidencia de tipos: no se puede convertir de LinkedList a List". –

0

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

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

Pero si acabo de quitar el tipo de lista en la declaración que parece tener la funcionalidad deseada .

LinkedList<Node>[] 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 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<>(); 
} 
0

Hace falta un conjunto de lista, una alternativa es intentar:

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

Entonces node_array[i] almacena la cabeza (primero) de un nodo (sea cual sea su aplicación lista de favoritos) ArrayList<IntegerNode> o LinkedList<IntegerNode>.

Bajo este diseño, perderá el método de acceso aleatorio list.get(index), pero aún podría recorrer la lista comenzando con el almacén de nodos head/fist en la matriz segura de tipo.

Esto podría ser una opción de diseño aceptable dependiendo de 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.

Cuestiones relacionadas