Question Initialisation d'une ArrayList sur une ligne


Je veux créer une liste d'options à des fins de test. Au début, j'ai fait ceci:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

Puis j'ai refacturé le code comme suit:

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

Y a-t-il une meilleure manière de faire cela?


2157
2018-06-17 04:10


origine


Réponses:


En fait, probablement le "meilleur" moyen d'initialiser le ArrayList est la méthode que vous avez écrite, car elle n'a pas besoin de créer une nouvelle List de quelque manière que:

ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");

Le hic, c'est qu'il y a pas mal de dactylographie nécessaire pour se référer à ça list exemple.

Il existe des alternatives, telles que la création d'une classe interne anonyme avec un initialiseur d'instance (également appelée "initialisation double accolade"):

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

Cependant, je ne suis pas très friands de cette méthode parce que ce que vous finissez avec est une sous-classe de ArrayList qui a un initialiseur d'instance, et cette classe est créée juste pour créer un objet - cela me semble un peu exagéré.

Ce qui aurait été bien si le Proposition de Littéraux de Collection pour Pièce de projet a été accepté (il devait être introduit dans Java 7, mais il ne devrait pas non plus faire partie de Java 8):

List<String> list = ["A", "B", "C"];

Malheureusement, cela ne vous aidera pas, car il initialisera un fichier immuable List plutôt qu'un ArrayListet, de plus, ce n'est pas encore disponible, si jamais il le sera.


1624
2018-06-17 04:13



Ce serait plus simple si vous deviez le déclarer comme List - Doit-il être un ArrayList?

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

Ou si vous n'avez qu'un seul élément:

List<String> places = Collections.singletonList("Buenos Aires");

Cela signifierait que places est immuable (essayer de le changer provoquera une UnsupportedOperationException exception à jeter).

Faire une liste mutable qui soit concrète ArrayList vous pouvez créer un ArrayList de la liste immuable:

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

1725
2018-06-17 04:15



La réponse simple

En Java 8 ou plus tôt:

List<String> strings = Arrays.asList("foo", "bar", "baz");

Cela vous donnera un List soutenu par le tableau, de sorte qu'il ne peut pas changer de longueur.
Mais vous pouvez appeler List.set, donc c'est encore mutable.


En Java 9:

List<String> strings = List.of("foo", "bar", "baz");

Cela vous donnera un immuable List, donc ça ne peut pas être changé.
C'est ce que vous voulez dans la plupart des cas où vous le précalculez.


La réponse la plus courte

Tu peux faire Arrays.asList encore plus court avec une importation statique:

List<String> strings = asList("foo", "bar", "baz");

L'importation statique:

import static java.util.Arrays.asList;  

Ce que tout IDE moderne vous suggérera et fera automatiquement pour vous.
Par exemple, dans IntelliJ IDEA, vous appuyez sur Alt+Enter et sélectionnez Static import method....


Cependant, je ne recommande pas de raccourcir le Java 9 List.of méthode, car ayant juste of devient confus.
List.of est déjà assez court et se lit bien.


En utilisant Streams

Pourquoi est-ce que ça doit être un List?
Avec Java 8 ou plus tard, vous pouvez utiliser un Stream ce qui est plus flexible:

Stream<String> strings = Stream.of("foo", "bar", "baz");

Vous pouvez concaténer Streams:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

Ou vous pouvez aller d'un Stream à un List:

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());

Mais de préférence, utilisez simplement le Stream sans le collecter à un List.


Si vous vraiment spécifiquement besoin d'un java.util.ArrayList

(Vous ne le faites probablement pas.)
Citer JEP 269 (Je souligne):

Il y a un petit ensemble de cas d'utilisation pour initialiser une instance de collection mutable avec un ensemble prédéfini de valeurs. Il est généralement préférable d'avoir ces valeurs prédéfinies dans une collection immutable, puis d'initialiser la collection mutable via un constructeur de copie.


Si tu veux tous les deux prépopuler un ArrayList  et ajouter par la suite (pourquoi?), utiliser

List<String> strings = new ArrayList<>(asList("foo", "bar", "baz"));

ou en Java 9:

List<String> strings = new ArrayList<>(List.of("foo", "bar", "baz"));

ou en utilisant Stream:

List<String> strings = Stream.of("foo", "bar", "baz")
                             .collect(toCollection(ArrayList::new));

Mais encore une fois, il vaut mieux simplement utiliser le Stream directement au lieu de le collecter à un List.


Programme aux interfaces, pas aux implémentations

Vous avez dit que vous avez déclaré la liste comme ArrayList dans votre code, mais vous ne devriez le faire que si vous utilisez un membre de ArrayList ce n'est pas dans List.

Ce que vous ne faites probablement pas.

Habituellement, vous devez simplement déclarer les variables par l'interface la plus générale que vous allez utiliser (par ex. Iterable, Collection, ou List), et les initialiser avec la mise en œuvre spécifique (par ex. ArrayList, LinkedList ou Arrays.asList()).

Sinon, vous limitez votre code à ce type spécifique, et il sera plus difficile de le modifier quand vous le souhaitez.

Par exemple:

// Iterable if you just need iteration, for (String s : strings):
Iterable<String> strings = new ArrayList<>();   

// Collection if you also need .size() or .stream():
Collection<String> strings = new ArrayList<>(); 

// List if you also need .get(index):
List<String> strings = new ArrayList<>();       

// Don't declare a specific list implementation
// unless you're sure you need it:
ArrayList<String> strings = new ArrayList<>();  // You don't need ArrayList

Un autre exemple serait toujours la déclaration d'une variable InputStream même si c'est généralement un FileInputStream ou un BufferedInputStream, parce qu'un jour bientôt vous ou quelqu'un d'autre voudra utiliser un autre type de InputStream.


580
2017-09-09 12:33



Si vous avez besoin d'une liste simple de taille 1:

List<String> strings = new ArrayList<String>(Collections.singletonList("A"));

Si vous avez besoin d'une liste de plusieurs objets:

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");

100
2017-08-30 04:33



Avec Goyave tu peux écrire:

ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

En Guava, il existe également d'autres constructeurs statiques utiles. Vous pouvez lire à leur sujet ici.


52
2017-07-29 13:24



Les littéraux de collection ne sont pas inclus dans Java 8, mais il est possible d'utiliser l'API Stream pour initialiser une liste en une ligne plutôt longue:

List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

Si vous devez vous assurer que votre List est un ArrayList:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));

32
2018-04-03 23:21



import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");

26
2018-05-12 13:14



Vous pouvez créer une méthode d'usine:

public static ArrayList<String> createArrayList(String ... elements) {
  ArrayList<String> list = new ArrayList<String>();
  for (String element : elements) {
    list.add(element);
  }
  return list;
}

....

ArrayList<String> places = createArrayList(
  "São Paulo", "Rio de Janeiro", "Brasília");

Mais ce n'est pas beaucoup mieux que votre premier refactoring.

Pour plus de flexibilité, il peut être générique:

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}

22
2018-05-04 00:57



Avec Java 9, comme suggéré dans Proposition d'amélioration du JDK - 269, cela pourrait être réalisé en utilisant littéraux de collection maintenant comme -

List<String> list = List.of("A", "B", "C");

Set<String> set = Set.of("A", "B", "C");

Une approche similaire s'appliquerait également Map ainsi que -

Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")

qui est similaire à Proposition de Littéraux de Collection comme indiqué par @coobird ainsi. En outre clarifié dans le document JEP -


Alternatives

Les changements de langue ont été considérés plusieurs fois, et rejetés:

Proposition de pièce de projet, 29 mars 2009 

Projet de pièce de monnaie, 30 mars 2009 

JEP 186 discussion sur lambda-dev, janvier-mars 2014

La langue   propositions ont été mises de côté de préférence à une proposition basée sur une bibliothèque   résumé dans ce message.

Enchaîné lire à peu près le même ~> Quel est le point de surcharge des méthodes Convenience Factory


17
2018-02-02 17:36