Inizializzazione di un ArrayList in una riga


Volevo creare un elenco di opzioni a scopo di test. All'inizio, ho fatto questo:

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

Quindi, ho rifattorizzato il codice come segue:

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

C'è un modo migliore per farlo?

Author: Shashanth, 2009-06-17

30 answers

In realtà, probabilmente il modo "migliore" per inizializzare ArrayList è il metodo che hai scritto, in quanto non ha bisogno di creare un nuovo List in alcun modo:

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

Il problema è che è necessario un po ' di digitazione per fare riferimento a quell'istanza list.

Esistono alternative, come creare una classe interna anonima con un inizializzatore di istanze (noto anche come "inizializzazione doppia parentesi"):

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

Tuttavia, non sono troppo affezionato a questo metodo perché ciò che si finisce con è una sottoclasse di ArrayList che ha un inizializzatore di istanze e quella classe viene creata solo per creare un oggetto-che mi sembra un po ' eccessivo.

Ciò che sarebbe stato bello era se la proposta Collection Literalsper Project Coin fosse stata accettata (era prevista l'introduzione in Java 7, ma non è probabile che faccia parte di Java 8.):

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

Sfortunatamente non ti aiuterà qui, poiché inizializzerà un List immutabile piuttosto che an ArrayList, e inoltre, non è ancora disponibile, se mai lo sarà.

 2116
Author: coobird, 2015-03-13 15:27:35

Sarebbe più semplice se lo dichiarassi semplicemente come List - deve essere un ArrayList?

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

O se hai un solo elemento:

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

Ciò significherebbe che placesè immutabile (provare a cambiarlo causerà la generazione di un'eccezione UnsupportedOperationException).

Per creare un elenco mutabile che sia un ArrayList concreto è possibile creare un ArrayList dall'elenco immutabile:

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
 2253
Author: Tom, 2016-06-16 21:38:30

La risposta semplice

In Java 9 o versioni successive, dopo l'aggiunta di List.of():

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

Con Java 10 o versioni successive, questo può essere abbreviato con la parola chiave var.

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

Questo ti darà un immutabile List, quindi non può essere cambiato.
Che è quello che vuoi nella maggior parte dei casi in cui lo stai prepopolando.


Java 8 o versioni precedenti:

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

Questo ti darà un List supportato da un array, quindi non può cambiare lunghezza.
Ma puoi chiamare List.set, quindi è ancora mutabile.


Puoi rendere Arrays.asList ancora più breve con un'importazione statica:

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

L'importazione statica:

import static java.util.Arrays.asList;  

Che qualsiasi IDE moderno suggerirà e farà automaticamente per te.
Ad esempio in IntelliJ IDEA si preme Alt+Enter e si seleziona Static import method....


Tuttavia, non consiglio di accorciare il metodo List.of a of, perché diventa confuso.
List.of è già abbastanza breve e legge bene.


Utilizzando Stream s

Perché deve essere un List?
Con Java 8 o versioni successive è possibile utilizzare un Stream che è più flessibile:

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

Puoi concatenare Stream s:

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

Oppure puoi passare da un Stream a un List:

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

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

Ma preferibilmente, basta usare il Stream senza raccoglierlo in un List.


Se si davvero specificamente bisogno di un java.util.ArrayList

(Probabilmente non lo fai.)
Per citare PEC 269 (enfasi mia):

Esiste un piccolo set di casi d'uso per l'inizializzazione di un'istanza di raccolta mutabile con un set predefinito di valori. Di solito è preferibile che quei valori predefiniti siano in una raccolta immutabile e quindi inizializzare la raccolta mutabile tramite un costruttore di copie.


Se si desidera sia prepopolare un ArrayList e aggiungere ad esso in seguito (perché?), usare

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

O in Java 8 o precedente:

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

O usando Stream:

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

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

Ma ancora una volta, è meglio usare solo il Stream direttamente invece di raccoglierlo in un List.


Programma alle interfacce, non alle implementazioni

Hai detto di aver dichiarato la lista come ArrayList nel tuo codice, ma dovresti farlo solo se stai usando un membro di ArrayList che non è in List.

Che molto probabilmente non stai facendo.

Di solito dovresti semplicemente dichiarare le variabili di più interfaccia generale che si intende utilizzare (ad esempio Iterable, Collection, o List) e inizializzarli con l'implementazione specifica (ad esempio ArrayList, LinkedList o Arrays.asList()).

Altrimenti stai limitando il tuo codice a quel tipo specifico e sarà più difficile cambiarlo quando lo desideri.

Ad esempio, se stai passando un ArrayList a 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 altro esempio potrebbe essere sempre dichiarare la variabile an InputStream anche se di solito è un FileInputStream o un BufferedInputStream, perché uno giorno presto tu o qualcun altro vorrete usare qualche altro tipo di InputStream.

 929
Author: Christoffer Hammarström, 2020-06-20 09:12:55

Se hai bisogno di un semplice elenco di dimensioni 1:

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

Se hai bisogno di un elenco di diversi oggetti:

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
 113
Author: Randyaa, 2017-05-27 21:31:06

Con Guava puoi scrivere:

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

In Guava ci sono anche altri utili costruttori statici. Puoi leggere su di loro qui .

 57
Author: Paweł Adamski, 2017-12-12 03:02:22

Con java-9 e versioni successive, come suggerito in JEP 269: Metodi di fabbrica di convenienza per le raccolte, questo potrebbe essere ottenuto utilizzando letterali di raccolta ora con -

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

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

Un approccio simile si applicherebbe anche a Map-

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

Che è simile a Collection Literals proposal come dichiarato da @coobird. Ulteriormente chiarito anche nel PEC -


Alternative

Sono state prese in considerazione modifiche linguistiche più volte, e respinto:

Progetto Coin Proposal, 29 marzo 2009

Progetto Coin Proposal, 30 marzo 2009

JEP 186 discussione su lambda-dev, gennaio-marzo 2014

La lingua le proposte sono state accantonate in preferenza a una proposta basata sulla biblioteca come riassunto in questo messaggio .

Related: Qual è il punto dei metodi di fabbrica di convenienza sovraccaricati per le raccolte in Java 9

 43
Author: Naman, 2020-06-20 09:12:55

I letterali di raccolta non sono entrati in Java 8, ma è possibile utilizzare l'API Stream per inizializzare un elenco in una riga piuttosto lunga:

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

Se devi assicurarti che il tuo List sia un ArrayList:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
 34
Author: Mark, 2014-04-03 23:21:48
import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
 31
Author: George, 2010-05-12 13:14:16

È possibile creare un metodo di fabbrica:

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

Ma non è molto meglio del tuo primo refactoring.

Per una maggiore flessibilità, può essere generico:

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}
 24
Author: Jordão, 2018-03-04 21:29:06

In Java 9 possiamo facilmente inizializzare un {[2] } in una singola riga:

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

O

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

Questo nuovo approccio di Java 9 ha molti vantaggi rispetto ai precedenti:

  1. Efficienza spaziale
  2. Immutabilità
  3. Filo sicuro

Vedi questo post per maggiori dettagli -> Qual è la differenza tra List.di e matrici.Lista?

 16
Author: Mohit Tyagi, 2018-03-04 22:29:01

Il modo più compatto per farlo è:

Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
 8
Author: Richard B, 2014-12-15 11:44:15

Usa semplicemente il codice sottostante come segue.

List<String> list = new ArrayList<String>() {{
            add("A");
            add("B");
            add("C");
}};
 8
Author: user2801794, 2017-12-12 02:57:48

Con Eclipse Collections puoi scrivere quanto segue:

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

Puoi anche essere più specifico sui tipi e se sono mutabili o Immutabili.

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

Puoi fare lo stesso anche con Set e borse:

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

Nota: Sono un committer per le collezioni Eclipse.

 8
Author: Donald Raab, 2019-05-01 01:53:10

Ecco un altro modo:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
 7
Author: Henok T, 2017-03-01 00:49:20

(Dovrebbe essere un commento, ma troppo lungo, quindi nuova risposta). Come altri hanno menzionato, il metodo Arrays.asList è di dimensioni fisse, ma non è l'unico problema con esso. Inoltre non gestisce molto bene l'ereditarietà. Ad esempio, supponiamo di avere quanto segue:

class A{}
class B extends A{}

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

Quanto sopra si traduce in un errore del compilatore, perché List<B> (che è ciò che viene restituito dagli array.asList) non è una sottoclasse di List<A>, anche se è possibile aggiungere Oggetti di tipo B a un oggetto List<A>. Per aggirare questo, devi fare qualcosa come:

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

Questo è probabilmente il modo migliore per farlo, esp. se hai bisogno di un elenco illimitato o hai bisogno di usare l'ereditarietà.

 7
Author: user439407, 2017-12-12 02:57:07

È possibile utilizzare le seguenti istruzioni:

Frammento di codice:

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

List<String> names = Arrays.asList(arr);
 6
Author: rashedcs, 2020-06-20 09:12:55

Come Tom ha detto :

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

Ma dal momento che ti sei lamentato di volere un ArrayList, dovresti innanzitutto sapere che ArrayList è una sottoclasse di List e potresti semplicemente aggiungere questa riga:

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

Anche se questo potrebbe farti lamentare delle "prestazioni".

In tal caso non ha senso per me, perché, poiché la tua lista è predefinita, non è stata definita come una matrice (poiché la dimensione è nota al momento dell'inizializzazione). E se questa è un'opzione per tu:

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

Nel caso in cui non ti preoccupi delle minori differenze di prestazioni, puoi anche copiare un array in un ArrayList molto semplicemente:

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

Va bene, ma in futuro è necessario un po ' di più che solo il nome della località, è necessario anche un codice del paese. Supponendo che questo sia ancora un elenco predefinito che non cambierà mai durante l'esecuzione, è opportuno utilizzare un set enum, che richiederebbe una nuova compilazione se l'elenco dovesse essere modificato in futuro.

enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}

Sarebbe diventa:

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;
    }
}

Enum hanno un metodo statico values che restituisce un array contenente tutti i valori dell'enum nell'ordine in cui sono dichiarati, ad esempio:

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

In quel caso immagino che non avresti bisogno del tuo ArrayList.

POST scriptumRandyaa ha dimostrato un altro bel modo usando il metodo di utilità statica Collezioni.addAll.

 5
Author: Ozzy, 2017-05-23 12:10:48

Java 9 ha il seguente metodo per creare un elenco immutabile :

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

Che è facilmente adattabile per creare una lista mutabile, se necessario:

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

Metodi simili sono disponibili per Set e Map.

 5
Author: user85421, 2016-12-06 09:57:49
List<String> names = Arrays.asList("2","@2234","21","11");
 4
Author: Ran Adler, 2015-09-23 13:18:51

Sì con l'aiuto degli array è possibile inizializzare l'elenco degli array in una riga,

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
 4
Author: Akash Manngroliya, 2016-09-13 05:54:55

Puoi usare StickyList da Cactoos:

List<String> names = new StickyList<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);
 4
Author: yegor256, 2017-06-25 17:48:17

Prova con questa riga di codice:

Collections.singletonList(provider)
 3
Author: Ant20, 2016-05-16 14:25:18

In Java, non puoi fare

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

Come è stato sottolineato, è necessario eseguire una doppia inizializzazione della parentesi graffa:

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

Ma questo potrebbe costringerti ad aggiungere un'annotazione @SuppressWarnings("serial") o generare un UUID seriale che è fastidioso. Inoltre, la maggior parte dei formattatori di codice lo scarterà in più istruzioni/righe.

In alternativa puoi fare

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

Ma allora potresti voler fare un @SuppressWarnings("unchecked").

Anche secondo javadoc dovresti essere in grado di farlo:

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

Ma non lo sono in grado di farlo compilare con JDK 1.6.

 2
Author: Dawg, 2012-02-13 22:44:20
Collections.singletonList(messageBody)

Se hai bisogno di avere un elenco di un elemento!

Collezioni è da java.pacchetto util .

 1
Author: ViliusK, 2015-04-03 09:30:38

Il modo migliore per farlo:

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

Basta creare una funzione che può avere tutti gli elementi che vuoi e chiamarla per aggiungerli in una riga.

 1
Author: Charif DZ, 2017-05-27 21:35:25

Ecco il codice di 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");

Dichiarazione: Sono lo sviluppatore di AbacusUtil.

 1
Author: user_3380739, 2019-01-27 22:46:36

Per me Array.asList() è il migliore e conveniente. Mi piace sempre inizializzare in questo modo. Se sei un principiante nelle collezioni Java, vorrei che facessi riferimento a inizializzazione ArrayList

 0
Author: Manoj Kumar, 2014-12-07 05:37:12

Perché non fare una semplice funzione di utilità che fa questo?

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

"ll" sta per "elenco letterale".

ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
 0
Author: Stefan Reich, 2017-12-04 11:23:08

è interessante notare che nessuno-liner con l'altro sovraccarico Stream::collect il metodo è elencato

ArrayList<String> places = Stream.of( "Buenos Aires", "Córdoba", "La Plata" ).collect( ArrayList::new, ArrayList::add, ArrayList::addAll );
 0
Author: Kaplan, 2019-10-04 15:04:11

In realtà, è possibile farlo in una riga:

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})
 -1
Author: Adrian, 2017-05-27 21:31:36