Sunday, October 01, 2017

Java 9: Creating Immutable Collections

Static factory methods have been added in JDK 9, to allow you to easily create immutable lists, sets and maps.

Immutable Lists

Use the List.of() static factory methods to create immutable lists.

// in JDK 9
List<String> list = List.of("foo", "bar");

// in JDK 8
List<String> list2 = Collections.unmodifiableList(Arrays.asList("foo", "bar"));

// in Guava
List<String> list3 = ImmutableList.of("foo", "bar");

Immutable Sets

Use the Set.of() static factory methods to create immutable sets.

// in JDK 9
Set<String> set = Set.of("foo", "bar");

// in JDK 8
Set<String> set2 = Collections.unmodifiableSet(
                       new HashSet<>(Arrays.asList("foo", "bar")));

// in Guava
Set<String> set3 = ImmutableSet.of("foo", "bar");

Immutable Maps

Use the Map.of() and Map.ofEntries() static factory methods to create immutable maps.

// in JDK 9
Map<String, Integer> map = Map.of("key1", 1, "key2", 2);
// for more than 10 key-value pairs, use Map.ofEntries
Map<String, Integer> map2 = Map.ofEntries(entry("key1", 1),
                                          entry("key2", 2));

// in JDK 8
Map<String, Integer> map3 = new HashMap<>();
map3.put("key1", 1);
map3.put("key2", 2);
map3 = Collections.unmodifiableMap(map3);

// in Guava
Map<String, Integer> map4 = ImmutableMap.of("key1", 1, "key2", 2);
// or, for more than 5 key-value pairs:
Map<String, Integer> map5 = ImmutableMap.<String, Integer>builder()
                                .put("key1", 1)
                                .put("key2", 2)
                                .build();

Implementation Details

It's interesting to look at the implementation of these static factory methods. They return a different class based on which method you use e.g. if you call List.of(e1) you get an instance of ImmutableCollections.List1 but if you call List.of(e1, e2) you get an instance of ImmutableCollections.List2. These are compact field-based classes that consume less heap space than their unmodifiable (or mutable) equivalents.

Note that the immutable collections returned by the static factory methods are not "wrapper" collections like those returned by Collections.unmodifiable. With an unmodifiable collection, you can still modify the underlying collection if you have a reference to it, but an immutable collection will always throw an exception if you try to modify it.

No comments:

Post a Comment