web-dev-qa-db-fra.com

Initialisation ArrayList équivalente à l'initialisation du tableau

Je suis conscient que vous pouvez initialiser un tableau pendant l'instanciation de la manière suivante:

String[] names = new String[] {"Ryan", "Julie", "Bob"};

Existe-t-il un moyen de faire la même chose avec un ArrayList? Ou dois-je ajouter le contenu individuellement avec array.add()?

251
Jonathan

Arrays.asList peut aider ici:

new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
332
meriton

Oui.

new ArrayList<String>(){{
   add("A");
   add("B");
}}

En fait, cela crée une classe dérivée de ArrayList<String> (le jeu d’accolades extérieur le fait), puis de déclarer un initialiseur statique (le jeu d’accolades intérieur). Il s’agit en fait d’une classe intérieure de la classe contenante et elle comportera donc un pointeur implicite this. Pas de problème, sauf si vous souhaitez le sérialiser ou si vous vous attendez à ce que la classe externe soit collectée.

Je comprends que Java 7 fournira constructions de langage supplémentaires pour faire exactement ce que vous voulez.

EDIT: les versions récentes Java fournissent davantage de fonctions utilisables pour la création de telles collections et méritent d’être explorées au-dessus de ce qui précède (fournies à une époque antérieure à ces versions)

60
Brian Agnew

Voici le plus proche que vous pouvez obtenir:

ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));

Vous pouvez aller encore plus simple avec:

List<String> list = Arrays.asList("Ryan", "Julie", "Bob")

En regardant la source de Arrays.asList, il construit un ArrayList, mais par défaut, il est converti en liste. Vous pouvez donc faire ceci (mais pas de manière fiable pour les nouveaux JDK):

ArrayList<String> list = (ArrayList<String>)Arrays.asList("Ryan", "Julie", "Bob")
33
Fred Haslam
Arrays.asList("Ryan", "Julie", "Bob");
24
John D

Eh bien, dans Java il n’existe pas de syntaxe littérale pour les listes, vous devez donc utiliser .add ().

Si vous avez beaucoup d'éléments, c'est un peu verbeux, mais vous pouvez soit:

  1. utiliser Groovy ou quelque chose comme ça
  2. utiliser Arrays.asList (array)

2 ressemblerait à quelque chose comme:

String[] elements = new String[] {"Ryan", "Julie", "Bob"};
List list = new ArrayList(Arrays.asList(elements));

Cela entraîne cependant une création d'objet inutile.

8
jayshao

La réponse sélectionnée est: ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));

Cependant, il est important de comprendre la réponse sélectionnée en interne, copie les éléments plusieurs fois avant de créer le tableau final, et il existe un moyen de réduire une partie de cette redondance.

Commençons par comprendre ce qui se passe:

  1. Tout d'abord, les éléments sont copiés dans le Arrays.ArrayList<T> créé par la fabrique statique Arrays.asList(T...).

    Cela ne produit pas la même classe que Java.lang.ArrayListdespite ayant le même nom de classe simple. Il n'implémente pas de méthodes telles que remove(int) malgré une interface de liste. Si vous appelez ces méthodes, il lancera un UnspportedMethodException. Mais si tout ce dont vous avez besoin est une liste de taille fixe, vous pouvez vous arrêter ici.

  2. Ensuite, le Arrays.ArrayList<T> construit dans # 1 est transmis au constructeur ArrayList<>(Collection<T>) où la méthode collection.toArray() est appelée pour le cloner.

    public ArrayList(Collection<? extends E> collection) {
    ......
    Object[] a = collection.toArray();
    }
    
  3. Ensuite, le constructeur décide d’adopter le tableau cloné ou de le copier à nouveau pour supprimer le type de sous-classe. Puisque Arrays.asList(T...) utilise en interne un tableau de type T, le même que celui que nous avons transmis en tant que paramètre, le constructeur refuse toujours d'utiliser le clone, à moins que T ne soit un objet pur. (Ex.: String, Integer, etc., tous sont à nouveau copiés car ils étendent Object).

    if (a.getClass() != Object[].class) {      
        //Arrays.asList(T...) is always true here 
        //when T subclasses object
        Object[] newArray = new Object[a.length];
        System.arraycopy(a, 0, newArray, 0, a.length);
        a = newArray;
    }
    array = a;
    size = a.length;
    

Ainsi, nos données ont été copiées 3x simplement pour initialiser explicitement ArrayList. Nous pourrions le réduire à 2x si nous forçons Arrays.AsList(T...) à construire un tableau Object [], afin que ArrayList puisse l'adopter ultérieurement, ce qui peut être fait comme suit:

(List<Integer>)(List<?>) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5));

Ou peut-être que simplement ajouter les éléments après la création pourrait encore être le plus efficace.

5
NameSpace

Celui-ci, ça va.

ArrayList<String> names = new ArrayList<String>();
Collections.addAll(names, "Ryan", "Julie", "Bob");
3
Ken de Guzman

Voici comment faire en utilisant l'interface courante de la bibliothèque op4j Java (la version 1.1 a été publiée le 10 décembre): -

List<String> names = Op.onListFor("Ryan", "Julie", "Bob").get();

C'est une bibliothèque très cool qui vous fait gagner une tonne de temps.

2
crsedgar