collections_refueled.png

Building Collections

Wednesday, November 15, 2017

Creating Collections with the new .of() method in JDK9

Collections have been around since JDK2. With JDK9 a new of() method is introduced to create Lists, Sets and Maps. How does it work and what are the caveats? This blog is based on the excellent talk ‘Collections Refueled’ by Stuart Marks at Devoxx Belgium 2017.

List.of()

List.of() provides an easy way to create a ‘collection-literal’. This is a Collection that is unmodifiable, meaning the add(), remove() and put() methods are not usable.

try {
    List<String> list = List.of("a", "b", "c");
    list.add("d");
} catch (Exception e) {
    e.printStackTrace();
}

java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:70)
    at java.base/java.util.ImmutableCollections$AbstractImmutableList.add(ImmutableCollections.java:76)

These don’t replace the conventional Collections that you can modify. However there are plenty of use cases where you have a Collection where you know the elements at initialization time and don’t want to change them over the course of the program.  They also help with space-efficiency and startup time.

Nulls and duplicates disallowed

None of these methods allow a null value. They will throw an exception when you try to enter one.

try {
    List.of("a", "b", "a", null);
} catch (Exception e) {
    e.printStackTrace();
}

java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:221)
    at java.base/java.util.ImmutableCollections$ListN.<init>(ImmutableCollections.java:233)
    at java.base/java.util.List.of(List.java:859)

The methods for Map and Set also disallow duplicates, as these are usually programmer or configuration error.

try {
    Set.of("a", "b", "c", "a");
} catch (Exception e) {
    e.printStackTrace();
}

java.lang.IllegalArgumentException: duplicate element: a
    at java.base/java.util.ImmutableCollections$SetN.<init>(ImmutableCollections.java:462)
    at java.base/java.util.Set.of(Set.java:520)

Randomized iteration order

The documentation of a set tells us that ‘The iteration order of set elements is unspecified and is subject to change’. In these Set’s it’s enforced by having a different iteration order every time you run the program. This will prevent accidently errors of code depending on an arbitrary iteration order sneaking in.

Set<String> set = Set.of("a", "b", "c");
set.forEach(System.out::print);

On the first run this code may result in bca. The second run it could be abc and the third run it’s cab.

Serializable

The instances of List, Set and Map coming from this .of() method are serializable.

List<String> orig = List.of("a", "b", "c");
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("C:\\Data\\list.ser"));) {
    out.writeObject(orig);
} catch (IOException e) {
    e.printStackTrace();
}

try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("C:\\Data\\list.ser"));) {
    List<String> list = (List) in.readObject();
    System.out.println(list);
    System.out.println(list.equals(orig));
} catch (IOException|ClassNotFoundException e) {
    e.printStackTrace();
}

The result of this code is [a, b, c] and true. Meaning the original list and the result from serializing and deserializing are the same.

Once JDK9 gets used ‘in the wild’ these methods will be a welcome addition to cleaner and easier to read code.

Newsletter

Stay up to date with our newsletter.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.