java - lists - Collections.unmodifiableList y copia defensiva
lists java (7)
Tal vez no entendí el significado y, de ser así, ¿cuál es la forma de escribir una copia defensiva de esa colección?
Típicamente, lo usarías de esa manera:
private List<Integer> a1 = Arrays.asList(1, 2, 3);
public List<Integer> getUnmodifiable() {
return Collections.unmodifiableList(a1);
}
Alguien que llama getUnmodifiable
y no tiene acceso al interno de su clase (es decir, no puede acceder a la variable privada a1
), no podrá modificar la lista devuelta.
Si escribo
List<Integer> a1 = Arrays.asList(1, 2, 3);
List<Integer> a2 = Collections.unmodifiableList(a1);
a2
es de solo lectura pero si escribo
a1.set(0,10);
entonces a2
también se modifica.
Si en la API se dice:
Devuelve una vista no modificable de la colección especificada. Este método permite a los módulos proporcionar a los usuarios acceso de "solo lectura" a las colecciones internas.
entonces, ¿por qué si modifico la colección original también se modifica la colección copiada como objetivo?
Tal vez no entendí el significado y, de ser así, ¿cuál es la forma de escribir una copia defensiva de esa colección?
La declaración:
Collections.unmodifiableList(a1);
devuelve un contenedor sobre la colección original cuyos métodos de modificación arrojan UnsupportedOperationException
.
El contenedor es de lectura, lo que significa que si modifica a1
, los cambios se reflejan en la colección envuelta a2
.
La idea es que no se puede modificar la lista a través de a2
.
La modificación de la lista a1
ciertamente modificará lo que ve en a2
- esto es intencionado.
Simplemente no tiene una forma pública de acceder a la lista a1
, y debe tener lo que quiere :)
la API dice que las colecciones internas en su caso, la colección no es interna
el punto es que cuando tienes una lista privada en la clase y un gettet para esa lista, entonces puedes desear que las personas que llaman del getter no puedan modificar la lista en caso de que tengas que devolver una lista umodificable. de lo contrario, la lista devuelta es solo una referencia a su lista interna / privada y, por lo tanto, su contenido puede modificarse.
a1
y a2
harán referencia a los mismos datos (memoria).
la parte no modificable viene, solo con a2
como entrada.
imágenes si está pasando a2
a un método donde espera que el método sea idempotente. tales casos a2
ayuda.
en resumen, no puede modificar los datos utilizando un puntero a2
.
Sí, lo entendiste correctamente. La idea es que el objeto devuelto por umodifiableCollection
no se puede cambiar directamente, pero podría cambiar a través de otros medios (efectivamente al cambiar la colección interna directamente).
Mientras algo tenga acceso a la lista interna, la colección "no modificable" podría cambiarse.
Es por eso que generalmente construyes una colección no modificable y te aseguras de que nada pueda llegar a la lista interna:
Collection<Integer> myUmodifiableCollection = Collection.umodifiableCollection(Arrays.asList(1, 2, 3));
Como nunca se hace referencia a la List
creada por asList
, esta es una colección realmente inmodificable.
La ventaja de este enfoque es que no necesita copiar la colección / lista original en absoluto, lo que evita usar la memoria y la potencia de cálculo.
Guava proporciona la clase ImmutableCollection
(y sus subclases, como ImmutableList
) que proporcionan colecciones inmutables verdaderas (generalmente copiando la fuente).
Si necesita una lista inmodificable e inmutable o, en otras palabras, una copia no modificable de la lista fuente sin dependencia de otras bibliotecas, intente esto:
Collections.unmodifiableList(Collections.list(Collections.enumeration(sourceList)))
Collections.list()
copia valores de su enumeración.