Sunday, August 7, 2022

Unmodifiable or Immutable List in Java

A List is considered unmodifiable if elements cannot be added, removed, or replaced from the list once the unmodifiable instance of a List is created. In this post we’ll see how Unmodifiable list was created before Java 9 and how it can be created Java 9 onward using Immutable List Static Factory Methods.


Creating Unmodifiable list before Java 9

Before Java 8, in order to create unmodifiable list Collections.unmodifiableList() method was used.

  • Collections.unmodifiableList(List<? extends T> list)- Returns an unmodifiable view of the specified list. Note that the list underneath can still be modified.
public class UnmodifiedList {
  public static void main(String[] args) {
    List<String> alphaList = new ArrayList<>();
    alphaList.add("a");
    alphaList.add("b");
    alphaList.add("c");
    alphaList.add("d");
    //List<String> alphaList = Arrays.asList("a", "b", "c", "d");
    List<String> aList = Collections.unmodifiableList(alphaList);
    alphaList.add("e");
    System.out.println("alphaList- " + alphaList);
    aList.add("f");
  }
}

Output

alphaList- [a, b, c, d, e]
Exception in thread "main" java.lang.UnsupportedOperationException
 at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1058)
 at org.netjs.Programs.UnmodifiedList.main(UnmodifiedList.java:20)

As you can see alphaList which is used to create unmodifiable list can still be modified though changing the unmodifiable list results in UnsupportedOperationException.

By using Arrays.asList to create list you can ensure that methods that change the size of the list can’t be called on the returned list.

public class UnmodifiedList {
  public static void main(String[] args) {
    List<String> alphaList = Arrays.asList("a", "b", "c", "d");
    List<String> aList = Collections.unmodifiableList(alphaList);
    alphaList.add("e");
    System.out.println("alphaList- " + alphaList);
    aList.add("f");
  }
}

Output

Exception in thread "main" java.lang.UnsupportedOperationException
 at java.base/java.util.AbstractList.add(AbstractList.java:153)
 at java.base/java.util.AbstractList.add(AbstractList.java:111)
 at org.netjs.Programs.UnmodifiedList.main(UnmodifiedList.java:13)

As you can see now the original list itself can’t call any size changing operation.

Creating Unmodifiable list in Java 9

The List.of (added in Java 9) and List.copyOf (added in Java 10) static factory methods provide a convenient way to create unmodifiable lists. The List instances created by these methods have the following characteristics-

  1. The collections returned by the convenience factory methods added in JDK 9 are conventionally immutable. Elements cannot be added, removed, or replaced from such a list. Elements cannot be added, removed, or replaced from such a list. Calling any mutator method on the List will always cause UnsupportedOperationException to be thrown.
  2. If the elements with in the list themselves are mutable, this may cause the List's contents to appear to change.
  3. Such lists can't be created with null elements any such attempt result in NullPointerException.
  4. Unmodifiable lists are serializable if all elements are serializable.
  5. The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.

List.of() method in Java

List.of() method static factory method is a convenient way to create unmodifiable lists Java 9 onward. This method has both fixed-argument form and varargs form. Fixed-argument form overloads up to 10 elements and the form of these method is as follows.

List.of(E e1)- Returns an unmodifiable list containing one element.

..

..

List.of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9)- Returns an unmodifiable list containing nine elements. 

List.of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)- Returns an unmodifiable list containing ten elements.

varargs form

  • List.of(E... elements)- Returns an unmodifiable list containing an arbitrary number of elements.

List.of() method Java example

public class UnmodifiedList {
  public static void main(String[] args) {
    List<String> alphaList = List.of("a", "b", "c", "d");
    System.out.println("alphaList- " + alphaList);
    // raises error
    alphaList.add("e");
  }
}

Output

alphaList- [a, b, c, d]
Exception in thread "main" java.lang.UnsupportedOperationException
 at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:72)
 at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:76)
 at org.netjs.Programs.UnmodifiedList.main(UnmodifiedList.java:10)

List.copyOf() method in Java

If you want to create an unmodifiable List using an existing collection then you can use copyOf() method.

  • List.copyOf(Collection<? extends E> coll)- Returns an unmodifiable List containing the elements of the given Collection, in its iteration order. The given Collection must not be null, and it must not contain any null elements. If the given Collection is subsequently modified, the returned List will not reflect such modifications.

List.copyOf() method Java example

public class UnmodifiedList {
  public static void main(String[] args) {
    List<String> alphaList = new ArrayList<>();
    alphaList.add("a");
    alphaList.add("b");
    alphaList.add("c");
    alphaList.add("d");
    List<String> aList = List.copyOf(alphaList);
    alphaList.add("e");
    System.out.println("alphaList- " + alphaList);
    System.out.println("aList- " + aList);
  }
}

Output

alphaList- [a, b, c, d, e]
aList- [a, b, c, d]

As you can see even if the original collection is modified the returned unmodifiable list doesn’t reflect such modification.

That's all for this topic Unmodifiable or Immutable List in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to Remove Duplicate Elements From an ArrayList in Java
  2. How to Sort a HashMap in Java
  3. HashSet in Java With Examples
  4. CopyOnWriteArrayList in Java With Examples
  5. Java Collections Interview Questions And Answers

You may also like-

  1. AtomicInteger in Java With Examples
  2. Java ScheduledThreadPoolExecutor - Task Scheduling in Java
  3. Livelock in Java Multi-Threading
  4. Reflection in Java - Getting Constructor Information
  5. Java Pass by Value or Pass by Reference
  6. Difference Between Encapsulation And Abstraction in Java
  7. String Slicing in Python
  8. Difference Between @Controller And @RestController Annotations in Spring

2 comments:

  1. public class UnmodifiedList {
    public static void main(String[] args) {
    List alphaList = Arrays.asList("a", "b", "c", "d");
    List aList = Collections.unmodifiableList(alphaList);
    alphaList.add("e");
    System.out.println("alphaList- " + alphaList);
    aList.add("f");
    }
    }
    in above exmple alphaList list object itself immutable one, so again no need to pass this alphaList object to Collections.unmodifiableList(). so comment it out

    ReplyDelete
    Replies
    1. No they are still different- Arrays.asList() returns a fixed-size list meaning operations that would change the size of the returned list are not permitted but you can still modify the existing element.
      Collections.unmodifiableList() method returns well an unmodifiable list.
      Run this code to dispel any doubts.
      public class UnmodifiedList {

      public static void main(String[] args) {
      List alphaList = Arrays.asList("a", "b", "c", "d");
      List aList = Collections.unmodifiableList(alphaList);
      alphaList.set(3, "e");
      System.out.println("alphaList- " + alphaList);

      aList.set(3, "f");
      System.out.println("aList- " + aList);
      }

      }

      Delete