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:
IntegerNode
est une classe que j'ai créée. Et, tous mes fichiers de classe sont emballés ensemble.
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:
Utilisation de la liste des listes au lieu du tableau des listes:
List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
Déclarer la classe spéciale pour Array of Lists:
class IntegerNodeList {
private final List< IntegerNode > nodes;
}
Pour une raison quelconque, vous devez convertir le type et faire la déclaration comme ceci:
myMatrix = (LinkedList<IntegerNode>[]) new LinkedList<?>[numRows];
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.
class IntegerNodeList extends LinkedList<IntegerNode> {}
IntegerNodeList[] myMatrix = new IntegerNodeList[numRows];
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?
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 .
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
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.
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<>();
}