4 Inmutable Collections¶
Inmutable Collections¶
Java 9 trajo consigo una serie de métodos estáticos factoría en las interfaces List
, Set
y Map
para la creación de listas, conjuntos y mapas inmutables, respectivamente. Así, por ejemplo, tenemos los métodos List.of(element...)
o List.copyOf(collection)
para crear listas inmutables, Set.of(element...)
o Set.copyOf(collection)
para crear conjuntos inmutables, y Map.of(key1, value1, key2, value2)
, Map.ofEntries(mapEntries...)
, o Map.copyOf(map)
para crear mapas inmutables.
Podemos considerar un objeto como inmutable si su estado no puede cambiar después de ser construido, manteniendo durante toda su vida los mismos datos. Si las colecciones creadas usando los métodos anteriores contienen a su vez objetos inmutables, entonces podemos afirmar que la colección es automáticamente thread-safe, ya que no se podrá modificar ni su estructura ni los elementos contenidos en ella. Si, por el contrario, la colección contiene objetos que son mutables, entonces no podrá ser considerada thread-safe, por mucho que no podamos cambiar su estructura.
Al crear una colección en la que no se puede modificar su estructura, podemos hacer que sea lo más eficiente posible en relación al consumo de espacio en memoria.
Debemos tener en cuenta que las colecciones inmutables no son lo mismo que las unmodifiable collections, ya que no son wrappers sobre una colección mutable. Corresponden a nuevas colecciones cuyos elementos son obtenidos a partir de la colección dada, pero una vez creada, la nueva colección no tiene relación alguna con la usada para establecer los elementos.
Así, las colecciones inmutables no permiten las operaciones de añadir, eliminar o reemplazar elementos, lanzando la excepción UnsupportedOperationException
. Sin embargo, si los elementos contenidos en la colección son mutables, entonces es posible que la colección parezca que haya sido modificada, cuando en realidad lo que se han reemplazado son los valores de sus elementos
Otra característica importante de las colecciones inmutables es que no pueden contener elementos null
. Cualquier intento de crear una colección inmutable con elementos null
lanzará la excepción NullPointerException
.
Veamos un ejemplo:
List<String> mutableList = new ArrayList<>();
mutableList.add("C");
mutableList.add("C++");
mutableList.add("Java");
List<String> inmutableList = List.copyOf(mutableList);
// Any attempt to modify list throws UnsupportedOperationException
try {
inmutableList.add("Go");
} catch (UnsupportedOperationException e) {
System.out.println("Add is an unsupported operation");
}
try {
inmutableList.set(0, "Go");
} catch (UnsupportedOperationException e) {
System.out.println("Set is an unsupported operation");
}
// Changes in original list don't affect inmutableList.
mutableList.add("Typescript");
System.out.println(inmutableList);
// Null is forbidden as value in inmutableList. Throws NullPointerException
List<String> mutableList2 = new ArrayList<>();
mutableList2.add("C");
mutableList2.add("C++");
mutableList2.add(null);
try {
List<String> inmutableList2 = List.copyOf(mutableList2);
} catch (NullPointerException e) {
System.out.println("Can't create an inmutable list with a null element");
}
try {
List<String> inmutableList2 = List.of("C", "C++", null);
} catch (NullPointerException e) {
System.out.println("Can't create an inmutable list with a null element");
}