Initialisierung eines Arraylist in einer Zeile
-
05-07-2019 - |
Frage
Ich möchte eine Liste von Optionen zu Testzwecken erstellen. Anfangs tat ich:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
Dann Refactoring ich den Code wie folgt:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Gibt es einen besseren Weg, dies zu tun?
Lösung
Eigentlich wohl der „beste“ Weg, um den ArrayList
zu initialisieren ist die Methode, die Sie geschrieben, da es keine neues List
in irgendeiner Art und Weise erstellen benötigt:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
Der Haken ist, dass es ziemlich viel Typisierung zu diesem list
Instanz verweisen erforderlich.
Es gibt Alternativen, wie eine anonyme innere Klasse mit einer Instanz initializer machen (auch als „Doppel-Klammer-Initialisierung“ bekannt):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Aber ich bin nicht allzu gern diese Methode, weil, was Sie am Ende mit einer Unterklasse von ArrayList
ist, die eine Instanz initializer hat, und diese Klasse erstellt wird, nur ein Objekt zu schaffen - die wie ein wenig scheint nur Overkill mir.
Was wäre schön gewesen war, wenn die Sammlung Literale Vorschlag für Projekt Münze angenommen wurde (es geplant wurde in Java 7 eingeführt werden, aber es ist nicht wahrscheinlich Teil von Java 8 entweder zu sein).
List<String> list = ["A", "B", "C"];
Leider wird es Ihnen hier nicht helfen, da es eher eine unveränderliche List
initialisieren wird als ein ArrayList
, und darüber hinaus, es ist noch nicht verfügbar, wenn es jemals sein wird.
Andere Tipps
Es wäre einfacher, wenn Sie sind einfach es als List
erklären - hat es eine Arraylist sein
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Oder wenn Sie nur ein Element:
List<String> places = Collections.singletonList("Buenos Aires");
Dies würde bedeuten, dass places
ist unveränderlich (es eine UnsupportedOperationException
Ausnahme verursacht zu ändern versucht geworfen werden).
Um eine veränderbare Liste zu machen, die ein konkretes ArrayList
sind Sie eine ArrayList
aus der unveränderlichen Liste erstellen:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Die einfache Antwort
In Java 10, 11, 12 oder später:
var strings = List.of("foo", "bar", "baz");
In Java 9 oder höher:
List<String> strings = List.of("foo", "bar", "baz");
Dies gibt Ihnen eine unveränderliche List
, so kann es nicht geändert werden.
Das ist, was man in den meisten Fällen wollen, wo Sie es sind Vorabauffüllen.
Java 8 oder früher:
List<String> strings = Arrays.asList("foo", "bar", "baz");
Dies wird Ihnen ein List
durch das Array gesichert, so kann es nicht Länge ändern.
Aber man kann List.set
nennen, so ist es immer noch wandelbar ist.
Sie können machen Arrays.asList
sogar mit einem statischen Import kürzer:
List<String> strings = asList("foo", "bar", "baz");
Der statische Import:
import static java.util.Arrays.asList;
Welche jede moderne IDE wird vorschlagen und automatisch für Sie tun.
Zum Beispiel in IntelliJ IDEA drücken Sie Alt+Enter
und wählen Static import method...
.
Allerdings empfehle ich nicht die Java 9 List.of
Verfahren verkürzt wird, weil mit nur of
verwirrend wird.
List.of
ist schon kurz genug und liest sich gut.
Mit Stream
s
Warum muss es an ein List
sein?
Mit Java 8 oder höher können Sie eine Stream
verwenden, die flexibler ist:
Stream<String> strings = Stream.of("foo", "bar", "baz");
Sie können Stream
s verketten:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Sie können auch von einem Stream
zu einem List
gehen:
import static java.util.stream.Collectors.toList;
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
Aber bevorzugt, benutzen Sie einfach die Stream
ohne es zu einem List
zu sammeln.
Wenn Sie wirklich müssen spezifisch eine java.util.ArrayList
(Sie wahrscheinlich nicht tun.)
Um Zitat JEP 269 (Hervorhebung von mir):
Es gibt einen kleinen Satz Anwendungsfälle für mit einer vorgegebenen Menge von Werten eine veränderbare Sammlung Instanz initialisiert wird. Es ist in der Regel vorzuziehen, diese vordefinierten Werte in einer unveränderlichen Sammlung zu haben, und dann auf die wandelbaren Sammlung über einen Copy-Konstruktor zu initialisieren.
Wenn Sie auf beide vorab ausgefüllt eine ArrayList
und hinzufügen, um es danach (warum?), Verwenden Sie
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
oder in Java 8 oder früher:
ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
oder mit Stream
:
import static java.util.stream.Collectors.toCollection;
ArrayList<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
Aber noch einmal, es ist besser, nur die Stream
direkt zu verwenden, anstatt sie zu einem List
zu sammeln.
Programm-Schnittstellen, nicht auf Implementierungen
Sie sagen, Sie die Liste als ArrayList
im Code deklariert haben, aber man sollte nur das tun, wenn Sie einige Mitglieder ArrayList
verwenden, die nicht in List
ist.
Was Sie wahrscheinlich nicht tun.
In der Regel sollten Sie nur Variablen deklarieren durch die allgemeinste Schnittstelle, die Sie verwenden möchten (z Iterable
, Collection
oder List
) und initialisieren sie mit der spezifischen Implementierung (z ArrayList
, LinkedList
oder Arrays.asList()
).
Ansonsten sind Begrenzung Sie Ihren Code auf diesen speziellen Typ, und es wird schwieriger sein, zu ändern, wenn Sie wollen.
Zum Beispiel, wenn Sie ein ArrayList
zu einem void method(...)
vorbei sind:
// 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
}
Ein weiteres Beispiel wäre immer Variable eine InputStream
erklärt, obwohl es in der Regel ein FileInputStream
oder ein BufferedInputStream
, denn eines Tages bald, was Sie oder jemand wird eine andere Art von InputStream
verwenden möchten.
Wenn Sie eine einfache Liste der Größe 1:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
Wenn Sie eine Liste von mehreren Objekten:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
Sammlung Literale hat es nicht in Java 8, aber es ist möglich, den Stream-API zu verwenden, um eine Liste in einer ziemlich langer Linie zu initialisieren:
List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());
Wenn Sie müssen sicherstellen, dass Ihr List
ist ein ArrayList
:
ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
Mit Java 9
, wie vorgeschlagen in JDK Enhancement Proposal - 269 , dies unter Verwendung erreicht werden könnte Sammlung Literalen 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 auch für Map
-
Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")
, die ähnlich Sammlung Literale Vorschlag als auch durch @coobird angegeben. Ferner sind in der JEP doc geklärt und -
Alternativen
Sprache ändert mehrmals in Betracht gezogen wurde, und abgelehnt:
Projekt Münze Vorschlag, 29. März 2009
Projekt Münze Vorschlag, 30. März 2009
JEP 186 Diskussion über Lambda-dev Januar -march 2014
Die Sprache Vorschläge wurden beiseite in den Vorzug einer Bibliothek basierenden Vorschlags als href="http://mail.openjdk.java.net/pipermail/lambda-dev/2014-March/011938.html" in diesem Nachricht.
Einschlägige => Was ist der Punkt überladener Convenience Factory-Methoden für Sammlungen in Java 9
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 die erste Refactoring.
Für mehr Flexibilität, kann es sein, generic:
public static <T> ArrayList<T> createArrayList(T ... elements) {
ArrayList<T> list = new ArrayList<T>();
for (T element : elements) {
list.add(element);
}
return list;
}
In Java 9 wir eine ArrayList
in einer einzigen Zeile leicht initialisieren können:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
oder
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Dieser neue Ansatz von Java 9 hat viele Vorteile gegenüber den vorherigen:
Sehen Sie diesen Beitrag für mehr Details ->
Mit Eclipse-Sammlungen Sie die folgende schreiben: Sie können auch etwas konkreter über die Typen und ob sie Mutable oder Immutable. Sie können auch das gleiche mit Sets und Taschen tun: . Hinweis: Ich bin ein Committer für Eclipse Sammlungen List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");
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");
über die kompakteste Art und Weise, dies zu tun ist:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
Hier ist eine andere Art und Weise:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
Einfach unten Code wie folgt verwenden.
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Sie können die folgenden Anweisungen verwenden:
Code-Snippet:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
(Sollte ein Kommentar sein, aber zu lang, so neue Antwort). Wie andere erwähnt haben, ist die Arrays.asList
Methode eine feste Größe, aber das ist nicht das einzige Problem mit ihm. Sie funktioniert auch nicht Erbe sehr gut. Zum Beispiel: Angenommen, Sie haben die folgende:
class A{}
class B extends A{}
public List<A> getAList(){
return Arrays.asList(new B());
}
Die obigen Ergebnisse in einem Compiler-Fehlern, weil List<B>
(das ist das, was von Arrays.asList zurückgegeben wird) nicht eine Unterklasse von List<A>
ist, auch wenn Sie Objekte vom Typ B zu einem List<A>
Objekt hinzufügen können. Um dies zu umgehen, müssen Sie tun, so etwas wie:
new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))
Dies ist wahrscheinlich der beste Weg, dies zu gehen zu tun, esp. wenn Sie eine unbegrenzte Liste benötigen oder Vererbung verwenden.
Wie Tom sagte :
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Aber da du zu wollen, eine Arraylist beschwert, sollten Sie zunächst wissen, dass Arraylist eine Unterklasse von List ist und man konnte einfach diese Zeile hinzufügen:
ArrayList<String> myPlaces = new ArrayList(places);
Obwohl, das könnte man von 'Leistung' machen beschweren.
In diesem Fall macht es keinen Sinn für mich machen, warum, da Ihre Liste ist vordefiniert es nicht als ein Array definiert wurde (da die Größe zum Zeitpunkt der Initialisierung bekannt ist). Und wenn das eine Option für Sie:
String[] places = {"Buenos Aires", "Córdoba", "La Plata"};
Falls Sie der kleineren Leistungsunterschiede kümmern sich nicht, dann können Sie auch eine Reihe an einem Arraylist kopieren sehr einfach:
ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));
Okay, aber in Zukunft müssen Sie ein bisschen mehr als nur die Ortsnamen, müssen Sie ein zu Ländercode. Unter der Annahme, dies ist immer noch eine vordefinierte Liste, die nie dann während der Laufzeit ändern Sie es passend, einen enum
Satz zu verwenden, die erneute Kompilierung erforderlich wäre, wenn die Liste benötigt, um in der Zukunft geändert werden.
enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}
würde:
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 ist eine statische values
Methode, die ein Array zurückgibt enthält alle Werte der Enumeration in der Reihenfolge, wie sie deklariert sind, z.
for (Places p:Places.values()) {
System.out.printf("The place %s has code %d%n",
p.name, p.code);
}
In diesem Fall ich denke, Sie würden Ihre Arraylist nicht benötigen.
P. S. Randyaa demonstriert eine weitere gute Möglichkeit, die statische Hilfsmethode mit Collections.addAll .
Java 9 hat die folgende Methode einer unveränderlich Liste zu erstellen:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
, die leicht angepasst ist, eine veränderbare Liste zu erstellen, falls erforderlich:
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
ähnliche Verfahren sind in Set
und Map
.
List<String> names = Arrays.asList("2","@2234","21","11");
Sie können mit StickyList
von Cactoos :
List<String> names = new StickyList<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
Versuchen Sie es mit dieser Codezeile:
Collections.singletonList(provider)
Ja, mit Hilfe von Arrays Sie Array-Liste in einer Zeile initialisieren können,
List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
In Java, können Sie nicht tun
ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Wie wurde darauf hingewiesen, müssen Sie eine doppelte Klammer Initialisierung tun:
List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};
Aber das kann man in Kraft einer Anmerkung @SuppressWarnings("serial")
Hinzufügen oder Entfernen eine serielle UUID erzeugen, die lästig ist. Auch die meisten Code Formatierer wird, dass in mehrere Anweisungen / Zeilen auszupacken.
Alternativ können Sie tun,
List<String> places = Arrays.asList(new String[] {"x", "y" });
aber dann möchten Sie vielleicht einen @SuppressWarnings("unchecked")
tun.
auch nach javadoc sollten Sie in der Lage sein, dies zu tun:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
Aber ich bin nicht in der Lage, es zu bekommen mit JDK 1.6 zu kompilieren.
Collections.singletonList(messageBody)
Wenn Sie bräuchten eine Liste von haben ein Element
Kollektionen ist von java.util Paket.
Der beste Weg, es zu tun:
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);
}
}
Erstellen Sie einfach eine Funktion, die so viele Elemente haben können, wie Sie wollen und nennen es sie in eine Zeile hinzuzufügen.
Hier ist der Code von 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");
. Erklärung: Ich bin der Entwickler AbacusUtil
Für mich Arrays.asList () ist die beste und bequemste. Ich mag immer so initialisieren. Wenn Sie ein Anfänger in Java Collections sind dann würde Ich mag Sie sich auf Arraylist Initialisierung
Warum nicht eine einfache Nutzenfunktion machen, das dies tut?
static <A> ArrayList<A> ll(A... a) {
ArrayList l = new ArrayList(a.length);
for (A x : a) l.add(x);
return l;
}
"ll
" steht für "wörtliche Liste".
ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
Ich bin eine Liste von messageTemplate aus einer XML-Datei im Pfad vor in statischem Kontext gespeichert Erstellen
public final class TemplateStore {
private TemplateStore(){}
private static final String [] VERSIONS = {"081"};
private static final String TEMPLATE_FILE_MASK = "template/EdiTemplates_v%s.xml";
private static final String ERROR = "Error In Building Edifact Message Template Store";
public static final List<MessageTemplate> TEMPLATE_LIST = Arrays.stream(VERSIONS)
.map(version -> TemplateStore.class
.getClassLoader().getResourceAsStream(String.format(TEMPLATE_FILE_MASK, version)))
.map(inputStream -> {
try {
return ((EdiTemplates) JAXBContext.newInstance(EdiTemplates.class).createUnmarshaller()
.unmarshal(inputStream)).getMessageTemplate();
} catch (JAXBException e) {
throw new IllegalArgumentException(ERROR, e);
}})
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
Eigentlich ist es möglich, sie in einer Zeile zu tun:
Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})