java immutability guava

java - ¿Cuál es la diferencia entre Collections.unmodifiableSet() y ImmutableSet of Guava?



immutability (4)

Además de la diferencia de comportamiento que menciona Jon, una diferencia importante entre ImmutableSet y el Set creado por Collections.unmodifiableSet es que ImmutableSet es un tipo . Puede pasar uno y dejar claro que el conjunto es inmutable utilizando ImmutableSet lugar de Set todo el código. Con Collections.unmodifiableSet , el tipo devuelto es simplemente Set ... por lo que solo queda claro que el conjunto no se puede modificar en el punto en que se crea, a menos que agregue Javadoc en todos los lugares donde pase ese Set diciendo "este conjunto no se puede modificar".

JavaDoc de ImmutableSet dice:

A diferencia de Collections.unmodifiableSet , que es una vista de una colección separada que aún puede cambiar, una instancia de esta clase contiene sus propios datos privados y nunca cambiará. Esta clase es conveniente para conjuntos finales públicos estáticos ("conjuntos constantes") y también le permite hacer fácilmente una "copia defensiva" de un conjunto proporcionado a su clase por un llamador.

Pero el ImmutableSet aún almacena referencia de elementos, no pude encontrar la diferencia para Collections.unmodifiableSet() . Muestra:

StringBuffer s=new StringBuffer("a"); ImmutableSet<StringBuffer> set= ImmutableSet.of(s); s.append("b");//s is "ab", s is still changed here!

¿Alguien podría explicarlo?


Considera esto:

Set<String> x = new HashSet<String>(); x.add("foo"); ImmutableSet<String> guava = ImmutableSet.copyOf(x); Set<String> builtIn = Collections.unmodifiableSet(x); x.add("bar"); System.out.println(guava.size()); // Prints 1 System.out.println(builtIn.size()); // Prints 2

En otras palabras, ImmutableSet es inmutable a pesar de que cualquier recopilación que se genere sea potencialmente cambiante, ya que crea una copia. Collections.unmodifiableSet impide que la colección devuelta se cambie directamente, pero sigue siendo una vista en un conjunto de respaldo potencialmente cambiante.

Tenga en cuenta que si comienza a cambiar el contenido de los objetos a los que hace referencia cualquier conjunto, todas las apuestas se desactivarán de todos modos. No hagas eso. De hecho, rara vez es una buena idea crear un conjunto usando un tipo de elemento mutable en primer lugar. (Lo mismo ocurre con los mapas que usan un tipo de tecla variable).


Kevin Bourrillion (desarrollador principal de Guava) compara colecciones inmutables / no modificables en esta presentación . Si bien la presentación tiene dos años de antigüedad y se centra en "Google Collections" (que ahora es una subparte de Guava), esta es una presentación muy interesante . La API puede haber cambiado aquí y allá (la API de Google Collections estaba en fase Beta en ese momento), pero los conceptos detrás de Google Collections / Guava siguen siendo válidos.

También podría estar interesado en esta otra pregunta de SO ( ¿Cuál es la diferencia entre ImmutableList de Google y Collections.unmodifiableList () ).


Una diferencia entre los dos que no se menciona en otras respuestas es que ImmutableSet no permite valores null , como se describe en el Javadoc

Un conjunto inmutable de alto rendimiento con un orden de iteración confiable y especificado por el usuario. No permite elementos nulos.

(La misma restricción se aplica a los valores en todas las colecciones inmutables de Guava).

Por ejemplo:

ImmutableSet.of(null); ImmutableSet.builder().add("Hi").add(null); // Fails in the Builder. ImmutableSet.copyOf(Arrays.asList("Hi", null));

Todos estos fallan en tiempo de ejecución. A diferencia de:

Collections.unmodifiableSet(new HashSet<>(Arrays.asList("Hi", null)));

Esto esta bien.