Frage Initialisierung einer ArrayList in einer Zeile


Ich möchte eine Liste von Optionen für Testzwecke erstellen. Zuerst habe ich Folgendes getan:

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

Dann habe ich den Code wie folgt umstrukturiert:

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

Gibt es einen besseren Weg, dies zu tun?


2157
2018-06-17 04:10


Ursprung


Antworten:


Eigentlich wahrscheinlich der "beste" Weg den zu initialisieren ArrayList ist die Methode, die Sie geschrieben haben, da es keine neue erstellen muss List in irgendeiner Weise:

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

Der Haken dabei ist, dass hier einiges an Schreibarbeit nötig ist list Beispiel.

Es gibt Alternativen, z. B. das Erstellen einer anonymen inneren Klasse mit einem Instanzinitialisierer (auch bekannt als "double brace initialization"):

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

Allerdings mag ich diese Methode nicht besonders, denn was Sie am Ende haben, ist eine Unterklasse von ArrayList Das hat einen Instanz-Initialisierer, und diese Klasse wird nur erstellt, um ein Objekt zu erstellen - das scheint mir nur ein bisschen übertrieben zu sein.

Was wäre schön gewesen, wenn die Vorschlag für Sammlungsliterale zum Projektmünze wurde akzeptiert (es war geplant, in Java 7 eingeführt zu werden, aber es ist wahrscheinlich auch nicht Teil von Java 8.):

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

Leider wird es dir hier nicht weiterhelfen, da es ein unveränderliches initialisieren wird List eher als ein ArrayListund außerdem ist es noch nicht verfügbar, wenn es jemals sein wird.


1624
2018-06-17 04:13



Es wäre einfacher, wenn Sie es einfach als a erklären würden List - Muss es eine ArrayList sein?

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

Oder wenn Sie nur ein Element haben:

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

Das würde das bedeuten places ist unveränderlich (Der Versuch, es zu ändern, wird ein UnsupportedOperationException Ausnahme, die ausgelöst werden soll).

Um eine veränderbare Liste zu erstellen, die konkret ist ArrayList Sie können ein erstellen ArrayList aus der unveränderlichen Liste:

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

1725
2018-06-17 04:15



Die einfache Antwort

In Java 8 oder früher:

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

Dies wird Ihnen einen geben List durch das Array unterstützt, so kann es nicht die Länge ändern.
Aber du kannst anrufen List.set, also ist es immer noch veränderlich.


In Java 9:

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

Dies wird Ihnen eine unveränderliche geben ListAlso kann es nicht geändert werden.
Was Sie in den meisten Fällen wünschen, in denen Sie es vorbesetzen.


Die kürzere Antwort

Du kannst das schaffen Arrays.asList noch kürzer bei einem statischen Import:

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

Der statische Import:

import static java.util.Arrays.asList;  

Was jede moderne IDE vorschlagen und automatisch für Sie tun wird.
Zum Beispiel in IntelliJ IDEA drücken Sie Alt+Enter und wählen Sie Static import method....


Ich empfehle jedoch nicht, Java 9 zu kürzen List.of Methode, weil gerade zu haben of wird verwirrend.
List.of ist schon kurz genug und liest gut.


Verwenden Streams

Warum muss es ein sein? List?
Mit Java 8 oder höher können Sie ein Stream welches ist flexibler:

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

Sie können verketten Streams:

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

Oder Sie können von einem gehen Stream zu einem List:

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

Aber vorzugsweise, benutze einfach die Stream ohne es zu sammeln List.


Wenn du Ja wirklich speziell brauchen a java.util.ArrayList

(Wahrscheinlich nicht.)
Zitieren JEP 269 (Hervorhebung von mir):

Da ist ein kleiner Satz von Anwendungsfällen zum Initialisieren einer änderbaren Sammlungsinstanz mit einer vordefinierten Menge von Werten. Es ist normalerweise vorzuziehen, diese vordefinierten Werte in einer unveränderbaren Sammlung zu haben und dann die veränderbare Sammlung über einen Kopierkonstruktor zu initialisieren.


Wenn du möchtest beide vorbevölkern ArrayList  und füge danach hinzu (warum?), benutze es

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

oder in Java 9:

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

oder verwenden Stream:

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

Aber noch einmal, es ist besser, nur das zu verwenden Stream direkt statt es zu sammeln List.


Programmiere zu Schnittstellen, nicht zu Implementierungen

Du hast gesagt, du hast die Liste als " ArrayList in Ihrem Code, aber Sie sollten das nur tun, wenn Sie ein Mitglied von verwenden ArrayList das ist nicht drin List.

Was du höchstwahrscheinlich nicht tust.

Normalerweise sollten Sie Variablen nur über die allgemeinste Schnittstelle deklarieren, die Sie verwenden werden (z. Iterable, Collection, oder List) und initialisieren sie mit der spezifischen Implementierung (z.B. ArrayList, LinkedList oder Arrays.asList()).

Andernfalls beschränken Sie Ihren Code auf diesen bestimmten Typ und es ist schwieriger, ihn zu ändern, wenn Sie möchten.

Beispielsweise:

// 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

Ein anderes Beispiel wäre, Variablen immer zu deklarieren InputStream obwohl es normalerweise ein FileInputStream oder ein BufferedInputStream, denn eines Tages werden Sie oder jemand anders bald etwas anderes brauchen InputStream.


580
2017-09-09 12:33



Wenn Sie eine einfache Liste der Größe 1 benötigen:

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

Wenn Sie eine Liste mehrerer Objekte benötigen:

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

100
2017-08-30 04:33



Mit Guave Du kannst schreiben:

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

In Guava gibt es auch andere nützliche statische Konstruktoren. Sie können über sie lesen Hier.


52
2017-07-29 13:24



Sammlungsliterale haben es nicht in Java 8 geschafft, aber es ist möglich, die Stream-API zu verwenden, um eine Liste in einer ziemlich langen Zeile zu initialisieren:

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

Wenn Sie sicherstellen müssen, dass Ihre List ist ein 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



Sie könnten eine Factory-Methode erstellen:

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

Aber es ist nicht viel besser als dein erstes Refactoring.

Für größere Flexibilität kann es generisch sein:

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



Mit Java 9, wie in vorgeschlagen JDK-Verbesserungsvorschlag - 269könnte dies erreicht werden mit Sammlungsliterale jetzt als -

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

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

Auch ein ähnlicher Ansatz würde gelten für Map auch -

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

das ist ähnlich Vorschlag für Sammlungsliterale wie auch von @coobird angegeben. Auch im GEP-Dokument geklärt -


Alternativen

Sprachänderungen wurden mehrfach berücksichtigt und abgelehnt:

Projektmünzvorschlag, 29. März 2009 

Projektmünzvorschlag, 30. März 2009 

JEP 186 Diskussion über Lambda-Dev, Januar-März 2014

Die Sprache   Vorschläge wurden zugunsten eines bibliotheksgestützten Vorschlags vorgezogen   zusammengefasst in diesem Botschaft.

Angekettet lesen Sie etwa gleich ~> Worum geht es bei überladenen Convenience Factory-Methoden?


17
2018-02-02 17:36