Collections – Factory Methoden

Ein Set, eine Liste oder eine Map im Code zu erstellen, hat in Java bisher recht viel Boilerplate-Code mit sich gebracht. Mit Java 9 wurden nun einige neue Factory-Methoden (JEP 269) eingeführt, mit denen die Erstellung, insbesondere von unveränderlichen Collections, sich auf eine Zeile ohne viel unnötigen Overhead reduzieren lässt.

Sets

Bisher sah die Erstellung eines Sets in etwa wie folgt aus:

Set<String> set = new HashSet<>();
set.add("Dies");
set.add("ist");
set.add("ein");
set.add("Test");
set = Collections.unmodifiableSet(set);

Dabei wird zunächst das Set erstellt. Anschließend werden die Elemente eingefügt und zuletzt wird aus dem bestehenden Set ein unveränderliches Set gemacht. Somit können anschließend keine Objekte mehr zum Set hinzugefügt oder aus dem Set entfernt werden. Dadurch kommt es nicht zu Fehler, wenn mehrere Threads das Set gleichzeitig verwenden sollen. Nichtsdestotrotz werden 6 Zeilen Code bei 4 Elementen im Set benötigt.

Deutlich kürzer geht es, indem man zunächst eine Liste erstellt, welche man dann dem Set im Konstruktor übergibt:

Set<String> set = Collections.unmodifiableSet(new HashSet<>(
    Arrays.asList("Dies", "ist", "ein", "Test")));		

Hier wird zunächst mit Arrays.asList eine Liste erstellt, aus der dann ein HashSet und daraus wiederum ein UnmodifiableSet erstellt wird.

Seit Java 8 kann das Problem auch mit Streams gelöst werden:

Set<String> set = Collections.unmodifiableSet(
  Stream.of("Dies", "ist", "ein", "Test")
  .collect(Collectors.toSet()));

Als erstes wird ein Stream mit den Strings erstellt. Anschließend werden die Elemente mit einem Set-Collector eingesammelt. Zum Schluss wird ein UnmodifiableSet erstellt.

Es fällt auf, dass bei allen Ansätzen die Strings einige Male kopiert werden müssen, bevor man ein UnmodifiableSet hat. Das ist ineffizient und benötigt viel Boilerplate-Code. Daher gibt es mit Java 9 dafür eine Factory-Methode:

Set<String> set = Set.of("Dies", "ist", "ein", "Test");

Die Methode Set.of(...) kann dabei beliebig viele Parameter von einem beliebigen aber festen Typ T erhalten. In unserem Fall erhält sie sechs Strings. Zurückgegeben wird direkt ein UnmodifiableSet. Hierdurch kann der Overhead stark reduziert werden.

Listen

Eine ähnliche Methode gibt es auch für die Erstellung von unveränderlichen Listen. Bisher konnte eine unveränderliche Liste zwar schon mit Arrays.asList(T...) erstellt werden, nun auch mit List.of(T...):

List<String> list1 = Arrays.asList("Dies", "ist", "ein", "Test");
List<String> list2 = List.of("Dies", "ist", "ein", "Test");

Während list1 vom Typ java.util.Arrays.ArrayList ist (nicht zu verwechseln mit java.util.ArrayList), ist list2 vom Typ java.util.ImmutableCollections.ListN. Beide Listen sind immutable.

Maps

Auch für Maps gibt es mit Java 9 zwei neue Factory-Methoden.

Map<Integer, String> map = Map.ofEntries(Map.entry(1, "Dies"), 
 Map.entry(2, "ist"), Map.entry(3, "ein"), Map.entry(4, "Test"));

Hier zu sehen ist die Map.ofEntries(...)-Methode. Ihr werden Objekte vom Typ Map.Entry übergeben. Diese können via Map.entry(...) erzeugt werden.

Da dabei immer noch sehr viel Boilerplate-Code benötigt wird, gibt es zusätzlich die Methode Map.of(...). Hier werden die Keys und Werte alle sequenziell übergeben. Dabei wird immer ein Schlüssel und anschließend der dazugehörige Wert übergeben. Danach der nächste Schlüssel, und so weiter. Die Methode akzeptiert bis zu 10 Schlüssel mit dem dazugehörigen Wert. Null-Objekte werden übrigens nicht akzeptiert. Hier ein Beispiel:

Map<Integer, String> map = Map.of(1, "Dies", 2, "ist", 3, 
  "ein", 4, "Test");

Die resultierende Map sieht bei beiden Ansätzen wie folgt aus:
{4=Test, 1=Dies, 2=ist, 3=ein}

Beide Maps sind außerdem vom Typ java.util.ImmutableCollections.MapN und damit ebenfalls nicht modifizierbar.

Zusammenfassung

Es gibt also einige neue Factory-Methode für die Collections. Dazu gehören:

  • Set.of(T...)
  • List.of(T...)
  • Map.of(K k1, V v2, K k3, V v3, ...) für bis zu 10 Schlüssel-Wert-Paare
  • Map.ofEntries(Map.Entry...)
Short URL for this post: https://wp.me/p4nxik-33J
This entry was posted in Java Basics and tagged , , . Bookmark the permalink.

Leave a Reply