web-dev-qa-db-fra.com

Impossible de créer un tableau de listes liées en Java ...?

Je travaille sur une classe de matrice clairsemée qui a besoin pour utiliser un tableau de LinkedList pour stocker les valeurs d'une matrice. Chaque élément du tableau (c'est-à-dire chaque LinkedList) représente une ligne de la matrice. Et, chaque élément du tableau LinkedList représente une colonne et la valeur stockée.

Dans ma classe, j'ai une déclaration du tableau comme:

private LinkedList<IntegerNode>[] myMatrix;

Et, dans mon constructeur pour le SparseMatrix, j'essaie de définir:

myMatrix = new LinkedList<IntegerNode>[numRows];

L'erreur que je reçois est

Impossible de créer un tableau générique de LinkedList<IntegerNode>.

Donc, j'ai deux problèmes avec ceci:

  1. Qu'est-ce que je fais mal et
  2. Pourquoi le type est-il acceptable dans la déclaration pour le tableau s'il ne peut pas être créé?

IntegerNode est une classe que j'ai créée. Et, tous mes fichiers de classe sont emballés ensemble.

99
kafuchau

Vous ne pouvez pas utiliser la création de tableaux génériques. C'est une faille/caractéristique des génériques Java génériques.

Les moyens sans avertissements sont:

  1. Utilisation de la liste des listes au lieu du tableau des listes:

    List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
    
  2. Déclarer la classe spéciale pour Array of Lists:

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

Pour une raison quelconque, vous devez convertir le type et faire la déclaration comme ceci:

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

Mis à part les problèmes de syntaxe, il me semble étrange d'utiliser un tableau et une liste liée pour représenter une matrice. Pour pouvoir accéder à des cellules arbitraires de la matrice, vous voudrez probablement qu'un tableau réel ou au moins un ArrayList contienne les lignes, car LinkedList doit parcourir toute la liste du premier élément à tout élément particulier, une opération O(n), par opposition à la fonction O(1) beaucoup plus rapide avec ArrayList ou un tableau réel.

Puisque vous avez mentionné que cette matrice est rare, cependant, une meilleure façon de stocker les données est peut-être une carte de cartes, où une clé dans la première carte représente un index de ligne, et sa valeur est une carte de ligne dont les clés sont un index de colonne , la valeur étant votre classe IntegerNode. Ainsi:

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 vous devez pouvoir parcourir la matrice ligne par ligne, vous pouvez faire en sorte que le mappage de ligne soit un TreeMap, et de même pour parcourir les colonnes dans l'ordre des index, mais si vous n'avez pas besoin de ces cas, HashMap est plus rapide que TreeMap. Des méthodes d'aide pour obtenir et définir une cellule arbitraire, gérant les valeurs nulles non définies, seraient bien sûr utiles.

5
Dov Wasserman
class IntegerNodeList extends LinkedList<IntegerNode> {}

IntegerNodeList[] myMatrix = new IntegerNodeList[numRows]; 
4
Bob

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

lancer de cette façon fonctionne mais vous laisse toujours un avertissement désagréable:

"Sécurité de type: l'expression de type List [] nécessite une conversion non contrôlée .."

Déclarer une classe spéciale pour Array of Lists:

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

est une idée intelligente pour éviter l'avertissement. peut-être un peu plus agréable est d'utiliser une interface pour cela:

public interface IntegerNodeList extends List<IntegerNode> {}

puis

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

compile sans avertissements.

n'a pas l'air trop mal, non?

3
user306708

Il n'y a pas de création de tableau générique dans Java 1.5 (ou 1.6 pour autant que je sache). Voir https://community.Oracle.com/message/4829402 .

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

Aucun avertissement. NetBeans 6.9.1, jdk1.6.0_24

2
Andrii

Vous avez besoin d'un tableau de List, une alternative est d'essayer:

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

Ensuite, node_array[i] Stocke le nœud principal (premier) d'un ArrayList<IntegerNode> Ou LinkedList<IntegerNode> (Quelle que soit votre implémentation de liste préférée).

Sous cette conception, vous perdez la méthode d'accès aléatoire list.get(index), mais vous pouvez toujours parcourir la liste en commençant par le magasin de nœuds head/fist dans le tableau de type sécurisé.

Cela peut être un choix de conception acceptable en fonction de votre cas d'utilisation. Par exemple, j'utilise cette conception pour représenter une liste d'adjacence de graphe, dans la plupart des cas d'utilisation, elle nécessite de toute façon de traverser la liste d'adjacence pour un sommet donné au lieu d'avoir un accès aléatoire à certains sommets de la liste.

0
Yiling

Si je fais ce qui suit, je reçois le message d'erreur en question

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

Mais si je supprime simplement le type de liste dans la déclaration, il semble avoir la fonctionnalité souhaitée.

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

Ces deux déclarations sont-elles radicalement différentes d'une manière dont je ne suis pas au courant?

MODIFIER

Ah, je pense que j'ai rencontré ce problème maintenant.

Itérer sur la matrice et initialiser les listes dans une boucle for semble fonctionner. Bien que ce ne soit pas aussi idéal que certaines des autres solutions proposées.

for(int i=0; i < matrix.length; i++){

    matrix[i] = new LinkedList<>();
}
0
Ryan