En Java, pourquoi la ligne de code suivante ne fonctionne-t-elle pas?
List<List<String>> myList = new ArrayList<ArrayList<String>>();
Cela fonctionne si je le change en
List<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();
Au début, je pensais que vous ne pouviez peut-être pas avoir de listes d’interface, mais je peux créer un List<Runnable>
très bien.
Des idées?
Les types génériques sont plus pédants.
List
signifie List
ou tout sous-type, mais <List>
signifie seulement List
. Si vous voulez un sous-type, vous devez avoir <? extends List>
Je suppose que vous pouvez utiliser
List<List<String>> myList = new ArrayList<List<String>>();
La raison pour laquelle vous ne pouvez pas faire cela est que vous pouvez utiliser une référence à une référence et avec un niveau d'indirection supplémentaire, vous devez faire attention.
// with one level of indirection its simple.
ArrayList alist = new ArrayList();
List list = aList; // all good
list = new LinkedList(); // alist is still good.
Avec les génériques, vous pouvez avoir deux niveaux d'indirection qui peuvent vous donner des problèmes, donc ils sont plus pédants pour éviter ces problèmes.
// with two levels of indirection
List<ArrayList> alist = new ArrayList<ArrayList>();
List<List> list = (List) alist; // gives you a warning.
list.add(new LinkedList()); // adding a LinkedList into a list of ArrayList!!
System.out.println(alist.get(0)); // runtime error
empreintes
Exception in thread "main" Java.lang.ClassCastException: Java.util.LinkedList
cannot be cast to Java.util.ArrayList
Commençons par ceci:
ArrayList<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();
Cela crée un ArrayList dont les éléments sont ArrayLists.
Supposons maintenant que nous puissions attribuer cela à
List<List<String>> myList2 = myList.
Maintenant, nous devrions pouvoir faire ceci:
myList2.add(new LinkedList<String>());
Mais cela signifie que nous avons ajouté une liste LinkedList à une liste dont les éléments sont supposés être ArrayLists. Ooops !!!
En réalité, l'attribution de myList
à myList2
n'est pas légale ... et cela garantit qu'il n'est pas possible d'ajouter le mauvais type de List<String>
à l'objet ArrayList<ArrayList<String>>
. (Non Peter, ce n'est pas juste pédantisme :-))
Seule la collection de niveau supérieur peut être déclarée en tant que classe d'implémentation, tandis que celles imbriquées doivent rester des interfaces jusqu'à ce que vous créiez des instances:
List<List<String>> rootList = new ArrayList<List<String>>();
et ensuite, lorsque vous créez un élément à intégrer, vous en faites une implémentation:
List<String> nodeList = new ArrayList<String>();
rootList.add(nodeList);
Sa comparaison Type
du côté gauche (déclaration) au Type
du côté droit (instanciation). À gauche, votre type est List<String>
alors qu'à droite, c'est ArrayList<String>
. Si se plaindre de la différence.
Veuillez mettre à jour le côté droit (instatiation) en tant que Liste i.e.
List<List<String>> myList = new ArrayList<List<String>>();
Cela devrait bien fonctionner.
list<list<string>> l1=new list<list<string>>();
est autorisé si la liste en contient une autre.
public final class CPanelXMLBuilder extends PanelXMLBuilder {
public CPanelXMLBuilder(AuthenticatedUser pAuthenticatedUser, Map<String, Object> pSessionMap, Map<String, Object> pRequestMap, String pPanelTemplate) throws Exception {
super(pAuthenticatedUser, pSessionMap, pRequestMap, pPanelTemplate, null);
}
public Map<String, Object> buildXMLDocument(List<List<String>> pDetailsList) {
if (pDetailsList.size() == 1) {
List<String> pCustomerDetail = pDetailsList.get(0);
xmlDocument.getRootElement().getChild("E_SHOW1").setText(pCustomerDetail.get(0));
xmlDocument.getRootElement().getChild("E_SHOW2").setText(pCustomerDetail.get(1));
xmlDocument.getRootElement().getChild("E_SHOW3").setText(pCustomerDetail.get(2));
xmlDocument.getRootElement().getChild("E_SHOW4").setText(pCustomerDetail.get(3));
xmlDocument.getRootElement().getChild("E_SHOW5").setText(pCustomerDetail.get(4));
xmlDocument.getRootElement().getChild("ServerTimestamp").setText(pCustomerDetail.get(5).substring(0, 19));
} else {
xmlDocument.getRootElement().getChild("AlertType").setText("INFO");
xmlDocument.getRootElement().getChild("Alert").setText("There is no matching record.");
}
requestMap.put(RequestMapKeys.XML_DOCUMENT, xmlDocument);
return requestMap;
}
}
Je sais que c'est une vieille question mais je voulais juste partager mon idée.
Au lieu de faire une liste de listes, je fais personnellement une liste de type [] (List<Type[]> listArray = new ArrayList<Type[]>();
), je génère une liste distincte de type (List<Type> list = new ArrayList<Type>();
), puis .add(list.toArray())
. De cette façon, il est plus clair et facile à lire que la syntaxe List of Lists, qui prête à confusion.
Par exemple, dans un projet récent où j'avais un fichier d'entrée où chaque ligne avec seulement un "0" signifiait une nouvelle ligne dans l'original (c'était un algorithme de cryptage):
String[] input = getInputContents(inFile);
List<String> currentBuffer = new ArrayList<String>();
List<String[]> buffers = new ArrayList<String[]>();
for(String line : input) {
if(line.equals("0")) {
buffers.add((String[])currentBuffer.toArray());
currentBuffer = new ArrayList<String>();
} else {
currentBuffer.add(line);
}
}