Java 9 provides as a way to create Empty immutable List, set and Map.
List list = List.of();
Set set = Set.of();
Map map = Map.of();
But
Whenever a class exposes an internal collection (through a public property, a getter etc) it either has to copy the entire collection or expose an immutable collection, to avoid the caller manipulating internal datastructures.
For example you could have some list of integers that's used internally but that's also exposed through a getter. Since the list is infrequently updated but often read, you decide to make the internal list immutable (making a new list on each update). That way your getter can just hand a reference to the internal list without copying anything. Now, sooner or later that list will have to be empty, necessitating an empty immutable list.
Well before Java 9, there were Collections.emptyList()
, Collections.emptySet()
, and Collections.emptyMap()
, which are explicitly and solely dedicated to producing unmodifiable empty collections. That List.of()
etc. can also do this is a matter of internal consistency of their API, not a revolutionary new feature.
But your main question seems to be
Please help me to understand the actual use case of an empty immutable list / set / map.
This is really three questions:
What are the use cases of empty collections?
Empty collections are useful because they are natural representations of situations that occur in real-world data and algorithms. For example, "Which passengers have checked in so far?" when none have. Which tasks are waiting to be dispatched? I could continue endlessly.
What are the use cases of unmodifiable collections?
A reference to an unmodifiable collection can be passed around without fear that the collection will be modified (via that reference, anyway). Note well that supposing the unmodifiability is appropriately documented, all participants in sharing that object can rely on it not to change. Among other things, this is important for safely sharing collections (and other unmodifiable objects) without making copies of them.
What use cases are in the intersection of those?
Empty collections occur naturally in real-world data and algorithms, so most use cases for unmodifiable collections are inclusive of empty collections.
Additionally, you did not ask but are perhaps overlooking that although you cannot add objects to an unmodifiable empty collection, you can replace it altogether with a non-empty collection, or serve up a non-empty collection the next time, or similar.
Just imagine a regular mathematical operation that is supposed to operate on those collections. Like computing the intersection of lists. The result can be empty, in this case this method would be of good use if the result should be immutable.
public List<E> intersectLists(List<E> first, List<E> second) {
// If one is empty, return empty list
if (first.isEmpty() || second.isEmpty()) {
// Before Java 9: return Collections.emptyList();
return List.of();
}
// Compute intersection
...
}
Immutable collections are often used when you expose internal data structures through getters but don't want the caller to be able to manipulate the collection.
A similar variant are unmodifiable collections. Those can be manipulated, if you have a direct reference to the mutable collection lying underneath the wrapper. By that you can force a user to use your designated methods for manipulation.
public Graph {
private List<Node> nodes;
// Other stuff
...
public List<Node> getNodes() {
// Wrap container to make list unmodifiable
return Collections.unmodifiableList(nodes);
}
// User should use designated methods to manipulate instead
public void addNode(Node node) { ... }
public void removeNode(Node node) { ... }
}