web-dev-qa-db-fra.com

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");

Ensuite, j'ai refactoré 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?

2551
Macarse

En fait, le "meilleur" moyen d'initialiser la ArrayList est probablement la méthode que vous avez écrite, car il n'est pas nécessaire de créer une nouvelle List:

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

Le problème, c'est qu'il faut pas mal de dactylographie pour faire référence à cette instance list.

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 n'aime pas trop cette méthode, car vous vous retrouvez avec une sous-classe de ArrayList qui a un initialiseur d'instance, et cette classe est créée uniquement pour créer un objet - cela semble être un peu un peu exagéré pour moi.

Qu'aurait été Nice si la proposition de collection Literals pour Project Coin était acceptée (elle devait être introduite dans Java 7, mais ce n'est pas le cas susceptibles de faire partie de Java 8 non plus.):

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

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

1890
coobird

Ce serait plus simple si vous deviez simplement le déclarer comme un List - faut-il que ce soit 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 la levée d'une exception UnsupportedOperationException).

Pour créer une liste modifiable concrète ArrayList, vous pouvez créer un ArrayList à partir de la liste immuable:

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

La réponse simple

Dans Java 10, 11, 12 ou version ultérieure:

var strings = List.of("foo", "bar", "baz");

Dans Java 9 ou version ultérieure:

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

Cela vous donnera un List immuable, donc il ne peut pas être changé.
C’est ce que vous voulez dans la plupart des cas où vous le pré-remplissez.


Java 8 ou version antérieure:

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

Cela vous donnera un List sauvegardé par le tableau, donc il ne peut pas changer de longueur.
Mais vous pouvez appeler List.set, il est donc toujours modifiable.


Vous pouvez rendre Arrays.asList encore plus court avec une importation statique:

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

L'import statique:

import static Java.util.Arrays.asList;  

Ce que tout IDE moderne 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 la méthode Java 9 List.of, car le simple fait de of devient déroutant.
List.of est déjà suffisamment court et lit bien.


Utiliser Streams

Pourquoi faut-il que ce soit un List?
Avec Java 8 ou version ultérieure, vous pouvez utiliser un Stream 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 passer d'un Stream à un List:

import static Java.util.stream.Collectors.toList;

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

Mais de préférence, utilisez simplement la Stream sans la collecter dans un List.


Si vous vraiment ​​avez besoin d'un Java.util.ArrayList

(Vous n'avez probablement pas.)
Pour citer JEP 269 (souligné par moi):

Il existe un petit ensemble de cas d'utilisation permettant d'initialiser une instance de collection modifiable avec un ensemble prédéfini de valeurs. Il est généralement préférable que ces valeurs prédéfinies soient dans une collection immuable, puis d'initialiser la collection mutable via un constructeur de copie.


Si vous voulez les deux pré-remplir une ArrayListet ​​y ajouter par la suite (pourquoi?), Utilisez

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

ou dans Java 8 ou version antérieure:

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

ou en utilisant Stream:

import static Java.util.stream.Collectors.toCollection;

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

Mais encore une fois, il vaut mieux utiliser directement la Stream au lieu de la collecter dans un List.


Programme aux interfaces, pas aux implémentations

Vous avez déclaré que vous aviez déclaré la liste en tant que ArrayList dans votre code, mais vous ne devriez le faire que si vous utilisez un membre de ArrayList qui 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 exemple, Iterable, Collection ou List), et les initialiser avec l’implémentation spécifique (par exemple, ArrayList, LinkedList ou Arrays.asList()).

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

Par exemple, si vous passez un ArrayList à un void method(...):

// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) { 
    for (String s : strings) { ... } 
}

// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
    if (!strings.isEmpty()) { strings.stream()... }
}

// List if you also need .get(index):
void method(List<String> strings) {
    strings.get(...)
}

// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
    ??? // You don't want to limit yourself to just ArrayList
}

Un autre exemple consisterait toujours à déclarer une variable InputStream même s’il s’agit généralement d’un FileInputStream ou d'un BufferedInputStream, car un jour, vous ou une autre personne voudrez utiliser un autre type de InputStream.

773

Si vous avez besoin d’une simple liste 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");
108
Randyaa

Avec Guava vous pouvez écrire:

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

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

55
Paweł Adamski

Les littéraux de collection ne se trouvaient pas dans Java 8, mais il est possible d'utiliser l'API Stream pour initialiser une liste dans 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
Mark
import com.google.common.collect.ImmutableList;

....

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

Avec Java 9, comme suggéré dans Proposition d'amélioration JDK - 269 , ceci pourrait être réalisé à l'aide de 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

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

qui est similaire à proposition Collection Literals , comme l'a également déclaré @coobird. Le doc du PEC précise également -


Alternatives

Les changements de langue ont été examinés à plusieurs reprises et rejetés:

Proposition de pièce de monnaie, 29 mars 2009

Proposition de pièce de monnaie, 30 mars 2009

Discussion du PEC 186 sur lambda-dev, janvier-mars 2014

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

Related => Quel est le problème des méthodes de fabrique de commodité surchargées pour les collections dans Java 9

23
Naman

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
Jordão

Dans Java 9, nous pouvons facilement initialiser un ArrayList sur une seule ligne:

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

ou

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

Cette nouvelle approche de Java 9 présente de nombreux avantages par rapport aux précédentes:

  1. efficacité spatiale
  2. Immutabilité
  3. Fil de sécurité

Voir ce post pour plus de détails -> Quelle est la différence entre List.of et Arrays.asList?

15
Mohit Tyagi

Avec Eclipse Collections , vous pouvez écrire ce qui suit:

List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");

Vous pouvez également être plus précis sur les types et s'ils sont mutables ou immuables.

MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Vous pouvez également faire la même chose avec Ensembles et Sacs:

Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Remarque: Je suis un partisan des collections Eclipse.

8
Donald Raab

Utilisez simplement le code ci-dessous comme suit.

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

Voici un autre moyen:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
7
Henok T

La manière la plus compacte de procéder est la suivante:

Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
7
Richard B

(Devrait être un commentaire, mais trop long, donc nouvelle réponse). Comme d'autres l'ont mentionné, la méthode Arrays.asList a une taille fixe, mais ce n'est pas le seul problème. De plus, il ne gère pas très bien l'héritage. Par exemple, supposons que vous ayez les éléments suivants:

class A{}
class B extends A{}

public List<A> getAList(){
    return Arrays.asList(new B());
}

Ce qui précède entraîne une erreur de compilation, car List<B> (qui est renvoyé par Arrays.asList) n'est pas une sous-classe de List<A>, même si vous pouvez ajouter des objets de type B à un List<A> objet. Pour résoudre ce problème, vous devez faire quelque chose comme:

new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))

C’est probablement la meilleure façon de procéder, en particulier. si vous avez besoin d'une liste illimitée ou avez besoin d'utiliser l'héritage.

6
user439407

Vous pouvez utiliser les déclarations ci-dessous:

Extrait de code:

String [] arr = {"Sharlock", "Homes", "Watson"};

List<String> names = Arrays.asList(arr);
6
rashedcs

Java 9 utilise la méthode suivante pour créer une liste immuable:

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

qui est facilement adapté pour créer une liste mutable, si nécessaire:

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

Des méthodes similaires sont disponibles pour Set et Map.

5
Carlos Heuberger

Comme dit Tom :

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

Mais puisque vous vous êtes plaint de vouloir une ArrayList, vous devez d’abord savoir que ArrayList est une sous-classe de List et vous pouvez simplement ajouter cette ligne:

ArrayList<String> myPlaces = new ArrayList(places);

Bien que, cela pourrait vous faire plaindre de "performance".

Dans ce cas, cela n’a aucun sens pour moi, car, puisque votre liste est prédéfinie, elle n’a pas été définie comme un tableau (car sa taille est connue au moment de l’initialisation). Et si c'est une option pour vous:

String[] places = {"Buenos Aires", "Córdoba", "La Plata"};

Si vous ne vous souciez pas des différences de performances mineures, vous pouvez également copier un tableau dans un ArrayList très simplement:

ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));

D'accord, mais à l'avenir, vous avez besoin d'un peu plus que le nom du lieu, vous avez également besoin d'un code de pays. En supposant qu'il s'agisse toujours d'une liste prédéfinie qui ne changera jamais pendant l'exécution, il convient d'utiliser un ensemble enum, ce qui nécessiterait une nouvelle compilation si la liste devait être modifiée ultérieurement.

enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}

deviendrait:

enum Places {
    BUENOS_AIRES("Buenos Aires",123),
    CORDOBA("Córdoba",456),
    LA_PLATA("La Plata",789);

    String name;
    int code;
    Places(String name, int code) {
      this.name=name;
      this.code=code;
    }
}

Les énumérations ont une méthode statique values qui renvoie un tableau contenant toutes les valeurs de l’énum dans l’ordre dans lequel elles ont été déclarées, par exemple:

for (Places p:Places.values()) {
    System.out.printf("The place %s has code %d%n",
                  p.name, p.code);
}

Dans ce cas, je suppose que vous n’auriez pas besoin de votre ArrayList.

P.S. Randyaa a démontré une autre manière agréable d'utiliser la méthode de l'utilitaire statique Collections.addAll .

5
Ozzy
List<String> names = Arrays.asList("2","@2234","21","11");
4
Ran Adler

Vous pouvez utiliser StickyList de Cactoos :

List<String> names = new StickyList<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);
4
yegor256

Essayez avec cette ligne de code:

Collections.singletonList(provider)
3
Ant20

Oui, à l’aide de tableaux, vous pouvez initialiser la liste de tableaux sur une ligne,

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
3
Akash Manngroliya

En Java, vous ne pouvez pas faire

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

Comme il a été souligné, vous devez effectuer une initialisation à double attache:

List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};

Mais cela peut vous obliger à ajouter une annotation @SuppressWarnings("serial") ou à générer un UUID série ennuyeux. En outre, la plupart des formateurs de code décompressent cela en plusieurs instructions/lignes.

Sinon, vous pouvez faire

List<String> places = Arrays.asList(new String[] {"x", "y" });

mais alors vous voudrez peut-être faire une @SuppressWarnings("unchecked").

Toujours selon javadoc, vous devriez pouvoir le faire:

List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

Mais je ne parviens pas à le compiler avec JDK 1.6.

2
Dawg

La meilleure façon de le faire:

package main_package;

import Java.util.ArrayList;


public class Stackkkk {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<Object>();
        add(list, "1", "2", "3", "4", "5", "6");
        System.out.println("I added " + list.size() + " element in one line");
    }

    public static void add(ArrayList<Object> list,Object...objects){
        for(Object object:objects)
            list.add(object);
    }
}

Créez simplement une fonction pouvant contenir autant d'éléments que vous le souhaitez et appelez-la pour les ajouter sur une seule ligne.

1
Elegant Odoo
Collections.singletonList(messageBody)

Si vous avez besoin d'une liste de n élément!

Les collections proviennent du package Java.util .

1
ViliusK

Voici le code par AbacusUtil

// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// The most efficient way, which is similar with Arrays.asList(...) in JDK. 
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");

Déclaration : Je suis le développeur de AbacusUtil.

1
user_3380739

Pourquoi ne pas créer une fonction utilitaire simple qui le fasse?

static <A> ArrayList<A> ll(A... a) {
  ArrayList l = new ArrayList(a.length);
  for (A x : a) l.add(x);
  return l;
}

"ll" signifie "liste littérale".

ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
0
Stefan Reich

Pour moi, Arrays.asList () est le meilleur et le plus pratique. J'aime toujours initialiser de cette façon. Si vous êtes débutant dans Java Collections, j'aimerais que vous vous référiez initialisation de ArrayList

0
Manoj Kumar