Open In App

Java Convenience Factory Methods for Collections

The JDK 9 has added static factory methods like of() onto basic Collection interfaces, to create unmodifiable collection objects. These are the same as the unmodifiable (immutable) collection we create in JDK 6, 7, 8. It allows you to create a list, set, and map of values in just one line. Java 9 doesn’t bring as many dramatic changes to our way of coding as its predecessor did, but surely we will have some fancy features.

 The belowmentioned ways lead to the creation of unnecessary objects. To overcome this problem, Java 9 has introduced static factory methods to create an immutable list, set, and map which will be discussed later on. prior to it let us revise the creation of an unmodifiable Collection prior to JDK 9 (JDK 7, 8).



List in JDK 8

List<String> listOfString = new ArrayList<>();
listOfString.add("Geeks");
listOfString.add("Java");
listOfString.add("Kotlin");
listOfString.add("Groovy");
listOfString.add("Scala");
listOfString = Collections.unmodifiableList(listOfString);

 Way 1: Using double-braces initialization



List<String> listOfString = Collections.unmodifiableList(new ArrayList<>() {

    {

        add(“Geeks”);

        add(“Java”);

        add(“Kotlin”);

        add(“Groovy”);

        add(“Scala”);

    }

});

Way 2: Using the Arrays API to convert an array to an ArrayList

List<String> listOfString = Collections.unmodifiableList(Arrays.asList(“Geeks”,”Java”,”Kotlin”,”Groovy”, “Scala”));

Way 3: Using the Stream API 

List<String> listOfString = Collections.unmodifiableList(Stream.of(“Bruce”,”Steve”,”Adrian”, “Dave”, “Janick”,”Nicko”).collect(toList()));

Why Java 9?

Now let us see benefits prior why to use Java 9 static factory methods before jumping on them

Now let us discuss the creation of an unmodifiable Collection in JDK. Here list, Set, and map are discussed below.

1. List in Java 9 

List<String> listOfString = List.of("Geeks", "Java", "Kotlin", "Groovy", "Scala");

Just one line of code is enough to create an Unmodifiable List, hence the creation of unnecessary objects is not involved.

An immutable list has an abstract base class  AbstractImmutableList<E> and four implementations:

Each of these types corresponds to the number of elements that are used to their creation. In the java.util.List interface, we have 12 static factory methods that use the above implementations to create immutable objects :

// creates empty immutable list
static <E> List<E> of()

// creates one-element immutable list
static <E> List<E> of(E e1)

// creates two-element immutable list
static <E> List<E> of(E e1, E e2)

// creates ten-element immutable list
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)

// creates N-element immutable list
static <E> List<E> of(E... elements)

Also do sneak out the methods that throw UnsupportedOperationException namely as follows

Inserting Null values will cause NullPointerException  as shown below

List<String> listOfString = List.of("Geeks","Java","Kotlin", "Scala", "Groovy", null);
// throws NullPointerException

Hence, the valid creation of an immutable list is as follows: 

List<String> listOfString = List.of("Geeks","Java","Kotlin", "Scala", "Groovy","Pearl");

2. Set in Java 9 

Illustration:

An immutable set is implemented similarly to how we saw with the List interface. It has an abstract base class  AbstractImmutableSet<E> and four implementations:

That again corresponds to the number of elements that are used in their creation. In the  java.util.Set interface, we have 12 static factory methods: 

// creates empty immutable set
static <E> Set<E> of()

// creates one-element immutable set
static <E> Set<E> of(E e1)

// creates two-element immutable set
static <E> Set<E> of(E e1, E e2)

// creates ten-element immutable set
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)

// creates N-element immutable set
static <E> Set<E> of(E... elements)

Methods that throw UnsupportedOperationException are as follows:

  1. add(E e), addAll(Collection<? extends E> c)
  2. remove(Object o), removeAll(Collection<?> c), removeIf(Predicate<? super E> filter)
  3. retainAll(Collection<?> c)
  4. clear()

Illustration:

Like with immutable lists, we cannot instantiate a Set with a null value as it does throw out NullPointerException where adding duplicate will lead to IllegalArgumentException as shown below:

Set<String> setOfString = Set.of("Geeks", "Java", "Kotlin", "Scala", "Groovy", null);
// throws NullPointerException

Set<String> setOfString = Set.of("Geeks", "Java", "Kotlin", "Java");
// throws IllegalArgumentException

Hence, the valid creation of an immutable set is as follows:

Set<String> setOfString = Set.of("Geeks", "Java", "Kotlin", "Scala", "Groovy", "Pearl");

3. Map in Java 9 

An immutable map has an abstract base class,  AbstractImmutableMap<K, V>, with three implementations:

Again we have the following set of factory methods inside the java.util.Map interface. 

// creates an empty map
static <K, V> Map<K, V> of()

// creates one-element map
static <K, V> Map<K, V> of(K k1, V v1)

// creates two-element map
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2)

// creates ten-element map
static <K, V> Map<K, V> 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)

// creates N-element map
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries)

Again the methods that throw an UnsupportedOperationException are as follows:

Illustration:

Inserting Null key or value will cause NullPointerException : 

Map<String, Integer> weightInKg = Map.of(null, 59, "John", 61);
// throws NullPointerExcepton because of null key
Map<String, Integer> weightInKg = Map.of("Ron", null, "John", 61);
// throws NullPointerExcepton because of null value
Map<String, Integer> weightInKg = Map.ofEntries(Map.entry("Ron", 59), null);
// throws NullPointerExcepton because of null entry

Adding duplicate key element will throw IllegalArgumentException:

Map<String, Integer> weightInKg = Map.of("Ron", 59, "Ron", 59);
Map<String, Long> weightInKg = Map.ofEntries(Map.entry("Ron", 59), Map.entry("Ron", 59));

Valid creation of an immutable map is as follows:

Map<String, Long> weightInKg = Map.of("Ron", 59, "John", 61, "Ed", 60, "Nick", 60, "Jack", 60L, "Ben", 65);
Map<String, Long> age = Map.ofEntries(Map.entry("Ron", 59),
                                      Map.entry("John", 61),
                                      Map.entry("Ed", 60),
                                      Map.entry("Nick", 60),
                                      Map.entry("Jack", 60),
                                      Map.entry("Ben", 65));

Article Tags :