Convenience Factory Methods for Collections in JDK 9 :
This article can be consider as continuation article for the Creating immutable collections before JDK 9. In this article we explained how JDK 9 solves the flaws of creating simple immutable collections. See JEP 269: Convenience Factory Methods for Collections
JDK 9 introduced of(
) static factory method in List
, Set
, Map
interfaces, by using the of()
static factory method of List
, Set
, Map
interfaces and ofEntries()
, and entry()
static factory methods of Map
interface its possible to create true immutable collections very easy.
List.of() :
JDK 9 added an overloaded of()
static factory method to the List interface. It provides a simple and way to create unmodifiable lists. Here are all the different versions of the of()
method:
static <E> List<E> of() - Returns an immutable list containing 0 elements static <E> List<E> of(E e1) - Returns an immutable list containing 1 elements static <E> List<E> of(E e1, E e2) static <E> List<E> of(E e1, E e2, E e3) static <E> List<E> of(E e1, E e2, E e3, E e4) static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) //varargs for arbitary elements static <E> List<E> of(E... elements)
The List instances created by these methods have the following characteristics :
- They are structurally immutable. Elements cannot be added, removed, or replaced. If we try to do so method will always cause UnsupportedOperationException to be thrown.
- They disallow null elements. Attempts to create them with null elements result in NullPointerException.
- The order of elements in the list is the same as the order of the provided arguments.
- They are serializable if all elements are serializable.
- The instances created by factory methods are value based. This means that factories are free to create a new instance or return an existing instance.
Immutable List example :
public class ImmutableListTest { public static void main(String[] args) { // Creating empty list List<String> emptyList = List.of(); //Creating immutable list List<String> immutableList = List.of("Peter", "Philip"); System.out.println("emptyList = " + emptyList); System.out.println("Immutable List = " + immutableList); //Try using null try { List>String< list = List.of("Peter",null, "Philip"); } catch (NullPointerException e) { System.out.println("nulls are not allowed in List.of()"); } // Try adding an element to immutable list try { immutableList.add("Gerhard"); } catch (UnsupportedOperationException e) { System.out.println("Cannot add an element to the immutable List"); } // Try removing an element from immutable List try { immutableList.remove(1); } catch (UnsupportedOperationException e) { System.out.println("Cannot remove an element from immutable List"); } } }
Output :
emptyList = [] Immutable List = [Peter, Philip] nulls are not allowed in List.of() Cannot add an element to the immutable List Cannot remove an element from immutable List
Set.of() :
JDK 9 added an overloaded of() static factory method to the Set interface. It provides a simple and way to create unmodifiable sets. Here are all the different versions of the of() method:
static <E> Set<E> of() - Returns an immutable set containing 0 elements static <E> Set<E> of(E e1) - Returns an immutable set containing 1 elements static <E> Set<E> of(E e1, E e2) static <E> Set<E> of(E e1, E e2, E e3) static <E> Set<E> of(E e1, E e2, E e3, E e4) static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5) static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6) static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) //varargs static <E> Set<E> of(E... elements)
The Set instances created by these methods have the following characteristics :
- They are structurally immutable. Elements cannot be added, removed, or replaced. If we try to do so method will always cause UnsupportedOperationException to be thrown.
- They disallow null elements. Attempts to create them with null elements result in NullPointerException.
- They reject duplicate elements at creation time. If you try to add existing set created by factory method throws IllegalArgumentException.
- The iteration order of set elements is unspecified.
- They are serializable if all elements are serializable.
- The instances created by factory methods are value based. This means that factories are free to create a new instance or return an existing instance.
Immutable Set example :
public class ImmutableSetTest { public static void main(String[] args) { // Creating empty Set Set<String> emptySet = Set.of(); //Creating immutable Set Set<String> immutableSet = Set.of("Peter", "Philip"); System.out.println("emptySet = " + emptySet); System.out.println("Immutable Set = " + immutableSet); //Try using null try { Set<String> set = Set.of("Peter",null, "Philip"); } catch (NullPointerException e) { System.out.println("nulls are not allowed in Set.of()"); } // Try adding an element to immutable Set try { immutableSet.add("Gerhard"); } catch (UnsupportedOperationException e) { System.out.println("Cannot add an element to the immutable Set"); } // Try removing an element from immutable Set try { immutableSet.remove(1); } catch (UnsupportedOperationException e) { System.out.println("Cannot remove an element from immutable Set"); } } }
Output :
emptySet = [] Immutable Set = [Peter, Philip] nulls are not allowed in Set.of() Cannot add an element to the immutable Set Cannot remove an element from immutable Set
Map.of() :
JDK 9 added an overloaded of() static factory method to the Map interface. It provides a simple and way to create unmodifiable key values. Here are all the different versions of the of() method.
static lt;K,Vgt; Maplt;K,Vgt; of() - Returns an immutable map containing 0 key vale static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1) - Returns an immutable map containing 1 key value static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2) static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2, K k3, V v3) static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) static lt;K,Vgt; Maplt;K,Vgt; of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10)
The Map instances created by these methods have the following characteristics :
- They are structurally immutable. Elements cannot be added, removed, or replaced. If we try to do so method will always cause UnsupportedOperationException to be thrown.
- They disallow null keys. Attempts to create key with null elements result in NullPointerException.
- They reject duplicate keys at creation time. If you try to add duplicate key to the existing map created by factory method throws IllegalArgumentException.
- The iteration order of map elements is unspecified.
- They are serializable if all keys are serializable.
- The instances created by factory methods are value based. This means that factories are free to create a new instance or return an existing instance. And can not predict implementation classes that are returned by factory methods.
Immutable Map example :
public class ImmutableMapTest { public static void main(String[] args) { // Creating immutable Empty map Map<Integer, String> emptyMap = Map.of(); //Creating immutable map Map<Integer, String> immutableMap = Map.of(1, "Peter", 2, "Gerhard"); System.out.println("emptyMap = " + emptyMap); System.out.println("Immutable Map = " + immutableMap); // Adding a null value try { Map<Integer, String> map = Map.of(1, "Peter", 2, null); } catch (NullPointerException e) { System.out.println("Nulls not allowed in Map.of()."); } // Adding new entry try { immutableMap.put(3, "Philip"); } catch (UnsupportedOperationException e) { System.out.println("Cannot add a new entry to immutable Map."); } // Adding Duplicate key/entry try { Map<Integer, String> map = Map.of(1, "Peter", 2, "Gerhard", 1, "Philip"); } catch (IllegalArgumentException e) { System.out.println(e.getMessage() + " Can not be added to the immutable list"); } // removing an entry from existing immutable map try { immutableMap.remove(1); } catch (UnsupportedOperationException e) { System.out.println("Cannot remove entry from immutable map"); } } }
Output :
emptyMap = {} Immutable Map = {2=Gerhard, 1=Peter} Nulls not allowed in Map.of(). Cannot add a new entry to immutable Map. duplicate key: 1 Can not be added to the immutable list Cannot remove entry from immutable map
Map.ofEntries() :
Similarly to List and Set, the of(…) method is overloaded to have 0 to 10 key-value pairs. If more than 10 arguments List and Set interfaces has var-arg methods, in the case of Map, there is no possibility to add var-args for key values, for this Map also has different method called ofEntries(). In below example entry is a static method of Map interface and its static import in example.
import java.util.Map; import static java.util.Map.entry; public class ImmutableMapTest2 { public static void main(String[] args) { Map<Integer,String> map = Map.ofEntries( entry(1, "Peter"), entry(2, "Gerhad"), entry(3, "Philip") ); System.out.println(map); } }
Also see related articles :
Creating immutable collections before JDK 9