Convertir ArrayList en chaîne de caractères[] array [dupliquer]

cette question a déjà une réponse ici:

je travaille dans l'environnement android et j'ai essayé le code suivant, mais il ne semble pas fonctionner.

String [] stockArr = (String[]) stock_list.toArray();

Si Je définir comme suit:

String [] stockArr = {"hello", "world"};

ça marche. Y a-t-il quelque chose que je manque?

939
demandé sur nullpointer 2011-03-21 08:57:59
la source

6 ответов

utilisez comme ceci.

List<String> stockList = new ArrayList<String>();
stockList.add("stock1");
stockList.add("stock2");

String[] stockArr = new String[stockList.size()];
stockArr = stockList.toArray(stockArr);

for(String s : stockArr)
    System.out.println(s);
1548
répondu Prince John Wesley 2015-04-13 23:45:25
la source

Essayez cette

String[] arr = list.toArray(new String[list.size()]);
838
répondu st0le 2018-05-03 22:51:22
la source

ce qui se passe, c'est que stock_list.toArray() crée un Object[] plutôt qu'un String[] et donc que le message type ne correspond pas à 1 .

le code correct serait:

  String [] stockArr = stockList.toArray(new String[stockList.size()]);

ou même

  String [] stockArr = stockList.toArray(new String[0]);

pour plus de détails, reportez-vous aux javadocs pour les deux surcharges de List.toArray .

cette dernière version utilise le tableau de longueur zéro pour déterminer le type du tableau de résultats. (Étonnamment, il est plus rapide de faire cela que de préallouer ... du moins, pour les versions récentes de Java. Voir https://stackoverflow.com/a/4042464/139985 pour plus de détails.)

d'un point de vue technique, la raison de ce comportement / design API est qu'une implémentation de la méthode List<T>.toArray() n'a aucune information sur ce que <T> est à l'exécution. Tout ce qu'il sait, c'est que le type d'élément brut est Object . Par contraste, dans l'autre cas, le paramètre array donne le type de base du tableau. (Si fournis tableau est assez grand pour contenir les éléments de la liste, il est utilisé. Sinon, un nouveau tableau du même type et d'une plus grande taille est attribué et retourné comme résultat.)


1 - en Java, un Object[] n'est pas compatible avec un String[] . Si c'était le cas, alors vous pourriez faire ceci:

    Object[] objects = new Object[]{new Cat("fluffy")};
    Dog[] dogs = (Dog[]) objects;
    Dog d = dogs[0];     // Huh???

c'est clairement un non-sens, et c'est pourquoi les types de tableaux ne sont généralement pas compatibles assignment.

267
répondu Stephen C 2018-10-01 12:34:58
la source

une alternative en Java 8:

String[] strings = list.stream().toArray(String[]::new);
119
répondu Vitalii Fedorenko 2014-04-20 20:29:58
la source

je peux voir beaucoup de réponses montrant comment résoudre le problème, mais seulement la réponse de Stephen essaie d'expliquer pourquoi le problème se produit donc je vais essayer d'ajouter quelque chose de plus sur ce sujet. C'est une histoire sur les raisons possibles pour lesquelles Object[] toArray n'a pas été changée en T[] toArray où les génériques sont introduits en Java.


pourquoi String[] stockArr = (String[]) stock_list.toArray(); wont work?

En Java, de type générique existe au moment de la compilation seulement . À l'exécution des informations sur le type générique (comme dans votre cas <String> ) est supprimé et remplacé par Object type (jetez un oeil à type erasure ). C'est pourquoi à l'exécution toArray() n'ont aucune idée de quel type précis à utiliser pour créer un nouveau tableau, de sorte qu'il utilise Object comme type le plus sûr, parce que chaque classe étend objet afin qu'il puisse stocker en toute sécurité l'instance de toute la classe.

maintenant le problème est que vous ne pouvez pas lancer l'instance de Object[] à String[] .

pourquoi? Jetez un coup d'oeil à cet exemple (supposons que class B extends A ):

//B extends A
A a = new A();
B b = (B)a;

bien qu'un tel code compilera, à l'exécution nous verrons lancer ClassCastException parce que l'instance détenue par référence a n'est pas réellement de type B (ou ses sous-types). Pourquoi ce problème (pourquoi cette exception doit être exprimés)? Une des raisons est que B pourrait avoir de nouvelles méthodes/champs que A n'a pas, il est donc possible que quelqu'un essaie d'utiliser ces nouveaux membres via b référence même si l'instance retenue ne les a pas (ne supporte pas). En d'autres termes, nous pourrions finir par essayer d'utiliser des données qui n'existent pas, ce qui pourrait conduire à de nombreux problèmes. Donc, pour prévenir une telle situation JVM jette l'exception, et arrêter plus de code potentiellement dangereux.

pourriez-vous demander maintenant "alors pourquoi ne sommes-nous pas arrêtés encore plus tôt? Pourquoi le code impliquant un tel casting est-il même compilable? Le compilateur ne devrait pas l'arrêter?". Réponse: non parce que le compilateur ne peut pas savoir avec certitude quel est le type d'instance réel détenu par la référence a , et il y a une chance qu'il retienne l'instance de classe B qui supportera l'interface de référence b . Regardez cet exemple:

A a = new B(); 
      //  ^------ Here reference "a" holds instance of type B
B b = (B)a;    // so now casting is safe, now JVM is sure that `b` reference can 
               // safely access all members of B class

revenons à vos tableaux. Comme vous le voyez en question, nous ne pouvons pas lancer l'instance de Object[] tableau de type plus précis String[] comme

Object[] arr = new Object[] { "ab", "cd" };
String[] arr2 = (String[]) arr;//ClassCastException will be thrown

Ici, le problème est un peu différent. Maintenant nous sommes sûrs que le tableau String[] n'aura pas de champs ou de méthodes supplémentaires parce que chaque tableau supporte seulement:

  • [] opérateur", 1519940920"
  • length déposée,
  • méthodes héritées de objet supertype,

donc c'est pas l'interface des tableaux qui le rend impossible. Le problème est que Object[] tableau à côté de Strings peut stocker n'importe quels objets (par exemple Integers ) de sorte qu'il est possible qu'un beau jour nous finirons par essayer d'invoquer la méthode comme strArray[i].substring(1,3) à l'exemple de Integer qui n'ont pas cette méthode.

donc pour faire sûr que cette situation va jamais arriver, dans les références Java array peut tenir seulement

  • instances de tableau de même type que Référence (Référence String[] strArr peut contenir String[] )
  • instances de tableau de sous-type ( Object[] peut contenir String[] parce que String est sous-type de Object ),

, mais ne peut pas tenir

  • tableau de supertype de type de tableau de référence ( String[] ne peut pas tenir Object[] )
  • tableau de type qui n'est pas relié au type de référence ( Integer[] ne peut pas contenir String[] )

en d'autres termes quelque chose comme ceci est OK

Object[] arr = new String[] { "ab", "cd" }; //OK - because
               //  ^^^^^^^^                  `arr` holds array of subtype of Object (String)
String[] arr2 = (String[]) arr; //OK - `arr2` reference will hold same array of same type as 
                                //     reference

vous pourriez dire que une façon de résoudre ce problème est de trouver à l'exécution le type le plus commun entre tous les éléments de liste et de créer un tableau de ce type, mais cela ne fonctionnera pas dans des situations où tous les éléments de liste seront d'un type dérivé d'un type générique. Jetez un oeil

//B extends A
List<A> elements = new ArrayList<A>();
elements.add(new B());
elements.add(new B());

maintenant le type le plus commun est B , pas A so toArray()

A[] arr = elements.toArray();

renvoie un tableau de B classe new B[] . Problème avec ce tableau est alors que le compilateur vous permettrait d'éditer son contenu en y ajoutant l'élément new A() , vous obtiendriez ArrayStoreException parce que le tableau B[] ne peut contenir que des éléments de la classe B ou de sa sous-classe , pour s'assurer que tous les éléments supportent l'interface de B , mais l'instance de A peut ne pas avoir toutes les méthodes/champs de B . Donc cette solution n'est pas parfaite.


la meilleure solution à ce problème est dire explicitement quel type de tableau toArray() devrait être retourné en passant ce type comme argument de méthode comme

String[] arr = list.toArray(new String[list.size()]);

ou

String[] arr = list.toArray(new String[0]); //if size of array is smaller then list it will be automatically adjusted.
81
répondu Pshemo 2017-05-23 14:47:36
la source

la bonne façon de procéder est:

String[] stockArr = stock_list.toArray(new String[stock_list.size()]);

j'aimerais ajouter aux autres bonnes réponses ici et expliquer comment vous avez pu utiliser les Javadocs pour répondre à votre question.

le Javadoc pour toArray() (aucun argument) est ici . Comme vous pouvez le voir, cette méthode retourne un Object[] et pas String[] qui est un tableau du type runtime de votre liste:

public Object[] toArray()

renvoie un tableau contenant tous les les éléments de cette collection. Si la collecte fait des garanties comme à quel ordre ses éléments sont retournés par son itérateur, cette méthode doit retourner les éléments dans le même ordre. Le tableau retourné sera "sûres", qu'aucune références sont maintenus par la collection. (En d'autres termes, cette méthode doit allouer un nouveau tableau, même si l' la collecte est soutenue par un Tableau). L'appelant est donc libre de modifier le tableau retourné.

juste au-dessous de cette méthode, cependant, est le Javadoc pour toArray(T[] a) . Comme vous pouvez le voir, cette méthode retourne un T[]T est le type de tableau que vous transmettez. Au début, cela ressemble à ce que vous cherchez, mais il n'est pas clair exactement pourquoi vous passez dans un tableau (est-ce que vous l'ajoutez, en l'utilisant pour juste le type, etc). Le la documentation indique clairement que le but du tableau passé est essentiellement de définir le type de tableau à retourner (qui est exactement votre cas d'utilisation):

public <T> T[] toArray(T[] a)

renvoie un tableau contenant tous les les éléments de cette collection; le runtime type du tableau retourné est que du tableau spécifié. Si la collection s'inscrit dans le tableau, il y est retourné. Sinon, un nouveau tableau est alloué avec le type d'exécution du tableau spécifié et la taille de ce tableau collection. Si la collection s'inscrit dans le tableau spécifié avec salle de spare (i.e., le tableau a plus d'éléments que la collection), Le élément dans le tableau qui suit immédiatement la fin de la collecte est réglé à null. Ceci est utile pour déterminer la longueur de la perception seulement si l'appelant sait que la collecte n'est pas contient aucun éléments null.)

si cette collection donne des garanties quant à l'ordre de ses éléments sont retournés par son itérateur, cette méthode doit retourner les éléments le même ordre.

cette implémentation vérifie si le tableau est assez grand pour contenir collection; si non, il attribue un nouveau tableau de la taille correcte et type (utilisant la réflexion). Puis, il itère sur la collection, enregistrement de chaque référence d'objet dans l'élément consécutif suivant de la tableau, en commençant par l'élément 0. Si le tableau est plus grand que le collection, un null est stocké dans le premier endroit après la fin de collection.

bien sûr, la compréhension des génériques (comme décrit dans les autres réponses) est nécessaire pour vraiment comprendre la différence entre ces deux méthodes. Néanmoins, si vous allez d'abord à la Javadoc, vous trouverez votre réponse et de voir par vous-même ce que vous devez savoir (si vous avez vraiment le faire).

notez aussi que lire les Javadocs ici vous aide à comprendre quelle devrait être la structure du tableau dans lequel vous passez. Bien que cela n'ait pas vraiment d'importance pratique, vous ne devriez pas passer dans un tableau vide comme celui-ci:

String [] stockArr = stockList.toArray(new String[0]);  

parce que, à partir du doc, cette implémentation vérifie si le tableau est assez grand pour contenir la collection; si non, elle allège un nouveau tableau de la taille et du type corrects (en utilisant la réflexion). il n'y a pas besoin de la hauteur supplémentaire dans la création d'un nouveau tableau quand vous pourriez facilement passer dans la taille.

comme c'est généralement le cas, les Javadocs vous fournissent une mine d'informations et de direction.

Hé attendez une minute, qu'est-ce que le reflet?

16
répondu Rick Hanlon II 2013-07-28 19:31:43
la source

Autres questions sur java arrays arraylist