Collections Factory Methods In JAVA

Table of contents

No heading

No headings in the article.

In this blog, we will try to understand the building of non-empty collections and maps. In the old days of Java let’s see how we used to create a list with elements:-

List<String> stringList = new ArrayList<>();
stringList.add("A");
stringList.add("B");
stringList = Collections.unmodifiableList(stringList);

Now let’s pause here for a moment and talk about the problems with this approach:-

  1. For a simple thing, this is a lot of code calling add each time.
  2. Collections.unModifiableList(List list) is not efficient as it always returns a new list even though the list passed in param itself is unModifiableList, the same is the case with Set and Maps. Below is the proof:-
    public static <T> List<T> unmodifiableList(List<? extends T> list) {
     return (list instanceof RandomAcces ?
             new UnmodifiableRandomAccessList<>(list) :
             new UnmodifiableList<>(list));
    }
    
    Now you can write much simpler code:-
List<String> stringList = List.of("one","two","three");

The above line has benefits as given below:-

  1. It gives us an immutable list.
  2. The list we get does not allow for null values. Who likes NullPointerExceptions?
  3. List.of() with no params gives you a singleton list.
  4. This implementation is serializable.
    Set<String> stringSet = Set.of("one","two","three","two");
    
    Adding “two” again gives us IllegalArgumentException as it does not make sense to have duplicates in a set.
    Map<Integer,String> stringList = Map.of(1,"one",2,"two");
    
    //Here 1st param is key and 2nd param is value In the map, we can keep 10 key-value pairs if we want to add more than that we can do as given below:-
List<String> stringList = ...;
stringList = strings.stream().map(String::toUpperCase).toList();

So this is the most interesting part as we think Stream.toList() let's say it as Type A is the same as Collectors.toList() let's say Type B but it is not. Type A produces an immutable list whereas Type B produces a good old ArrayList. In Certain cases we have better performances when using Type A for example when we know the list size beforehand. Stream has a SIZED property which Type A list reads and creates a list of the same size if possible. Otherwise every time list is getting full it will be copied to a bigger array which has its own overhead which happens internally.

Another way to create a list is:-

List<String> stringList = Arrays.asList("One","two","three");
stringList.add("four"); //UnsupportedOperationException
stringList.replaceAll(String::toUpperCase); //Correct

You will think that this list is immutable but that is not correct. The way to look at it is as a wrapper to an array. Once we create an array the size is fixed we cannot add or remove elements but we can change the existing element of Arrays.asList(). We can put null values also.

Let’s summarise what we have learnt :-

image.png

Do not forget to like and share if you like the content and be in touch for more tech and spiritual blogs.

Meditate and be at peace :)