Java-Listeninitialisierung in einer Zeile

1. Einleitung

In diesem kurzen Tutorial untersuchen wir, wie wir eine Liste mit Einzeilern initialisieren können .

2. Erstellen Sie aus einem Array

Wir können eine Liste aus einem Array erstellen und dank Array-Literalen können wir sie in einer Zeile initialisieren:

List list = Arrays.asList(new String[]{"foo", "bar"});

Wir können darauf vertrauen, dass der varargs-Mechanismus die Array-Erstellung übernimmt. Auf diese Weise können wir präziseren und lesbareren Code schreiben:

@Test public void givenArraysAsList_thenInitialiseList() { List list = Arrays.asList("foo", "bar"); assertTrue(list.contains("foo")); }

Die Ergebnisinstanz dieses Codes implementiert die List- Schnittstelle, ist jedoch weder eine java.util.ArrayList noch eine LinkedList . Stattdessen handelt es sich um eine Liste, die vom ursprünglichen Array unterstützt wird und zwei Auswirkungen hat.

Der Name der Klasse lautet zwar ArrayList, aber im Paket java.util.Arrays .

2.1. Feste Größe

Die Ergebnisinstanz von Arrays.asList hat eine feste Größe:

@Test(expected = UnsupportedOperationException.class) public void givenArraysAsList_whenAdd_thenUnsupportedException() { List list = Arrays.asList("foo", "bar"); list.add("baz"); }

2.2. Gemeinsame Referenz

Das ursprüngliche Array und die Liste haben dieselben Verweise auf die Objekte:

@Test public void givenArraysAsList_whenCreated_thenShareReference(){ String[] array = {"foo", "bar"}; List list = Arrays.asList(array); array[0] = "baz"; assertEquals("baz", list.get(0)); }

3. Aus einem Stream erstellen (Java 8)

Wir können einen Stream problemlos in jede Art von Sammlung konvertieren .

Daher können wir mit den Factory-Methoden für Streams Listen in einer Zeile erstellen und initialisieren:

@Test public void givenStream_thenInitializeList(){ List list = Stream.of("foo", "bar") .collect(Collectors.toList()); assertTrue(list.contains("foo")); }

Wir sollten hier markieren, dass Collectors.toList () nicht die genaue Implementierung der zurückgegebenen Liste garantiert .

Es gibt keinen allgemeinen Vertrag über die Veränderbarkeit, Serialisierbarkeit oder Thread-Sicherheit der zurückgegebenen Instanz. Daher sollte sich unser Code nicht auf eine dieser Eigenschaften stützen.

Einige Quellen weisen darauf hin, dass Stream.of (…) .collect (…) möglicherweise einen größeren Speicher- und Leistungsbedarf als Arrays.asList () hat, aber in fast allen Fällen handelt es sich um eine solche Mikrooptimierung , dass es kaum Unterschiede gibt.

4. Factory-Methoden (Java 9)

In JDK 9 wurden verschiedene praktische Factory-Methoden für Sammlungen eingeführt:

List list = List.of("foo", "bar", "baz"); Set set = Set.of("foo", "bar", "baz");

Ein wichtiges Detail ist, dass die zurückgegebenen Instanzen unveränderlich sind . Darüber hinaus bieten die Werksverfahren mehrere Vorteile hinsichtlich Raumeffizienz und Gewindesicherheit.

Dieses Thema wird in diesem Artikel ausführlicher behandelt.

5. Double-Brace-Initialisierung

An mehreren Stellen finden wir eine Methode namens "Double Brace Initialization", die wie folgt aussieht:

@Test public void givenAnonymousInnerClass_thenInitialiseList() { List cities = new ArrayList() {{ add("New York"); add("Rio"); add("Tokyo"); }}; assertTrue(cities.contains("New York")); }

Der Name "Double Brace Initialization" ist ziemlich irreführend. Die Syntax mag kompakt und elegant aussehen, verbirgt aber gefährlich, was unter der Haube vor sich geht.

In Java gibt es eigentlich kein 'Double Brace'- Syntaxelement. Dies sind zwei Blöcke, die absichtlich auf diese Weise formatiert wurden.

Mit den äußeren Klammern deklarieren wir eine anonyme innere Klasse, die eine Unterklasse der ArrayList sein wird . In diesen Klammern können wir die Details unserer Unterklasse deklarieren.

Wie üblich können wir Instanzinitialisierungsblöcke verwenden, und von dort stammt das innere Klammerpaar.

Die Kürze dieser Syntax ist verlockend, wird jedoch als Anti-Pattern angesehen.

Weitere Informationen zur Initialisierung mit Doppelklammern finden Sie in unserem Artikel hier.

6. Fazit

Modernes Java bietet mehrere Optionen zum Erstellen einer Sammlung in einer Zeile. Die Methode, die wir gewählt haben, hängt fast ausschließlich von persönlichen Vorlieben ab und nicht von technischen Überlegungen.

Ein wichtiger Aspekt ist, dass das Anti-Muster der anonymen Initialisierung der inneren Klasse (auch bekannt als "Doppelklammer") viele negative Nebenwirkungen hat , obwohl es anmutig aussieht .

Wie immer ist der Code auf GitHub verfügbar.