sort example ejemplo java final unmodifiable

example - order list object java



¿Qué hace Collections.unmodifiableSet() en Java? (5)

El Collections.unmodifiableSet(Set<? extends T>) creará un contenedor en el set original. Este conjunto de envoltorio no puede ser modificado. pero aún así el conjunto original puede ser modificado.

Ejemplo:

Set<String> actualSet=new HashSet<String>(); //Creating set

Añadiendo algunos elementos.

actualSet.add("aaa"); actualSet.add("bbb");

Imprimiendo elementos añadidos

System.out.println(actualSet); //[aaa, bbb]

Coloque el actualSet en un conjunto no modificable y asignado a una nueva referencia ( wrapperSet ).

Set<String> wrapperSet=Collections.unmodifiableSet(orginalSet);

Imprimir el wrapperSet. por lo que tendrá valores actualSet

System.out.println(wrapperSet); //[aaa, bbb]

intentemos eliminar / agregar un elemento en wrapperSet .

wrapperSet.remove("aaa"); //UnSupportedOperationException

Añadir un elemento más en actualSet

actualSet .add("ccc");

Imprimir actualSet y wrapperSet . Ambos valores de conjunto son iguales. así que si agrega / elimina elementos en el conjunto real, los cambios también se reflejarán en el conjunto de envoltura.

System.out.println(actualSet); //[aaa, ccc, bbb] System.out.println(wrapperSet); // [aaa, ccc, bbb]

Uso:

Este Collections.unmodifiableSet(Set<? extends T>) se usa para evitar la modificación del método getter de Set de cualquier objeto. Digamos

public class Department{ private Set<User> users=new HashSet<User>(); public Set<User> getUsers(){ return Collections.unmodifiableSet(users); } }

Puedo ver que Collections.unmodifiableSet devuelve una vista no modificable del conjunto dado, pero no entiendo por qué no podemos usar el modificador final para lograr esto.

En mi entendimiento, final declara una constante: algo que no puede ser modificado. Por lo tanto, si un conjunto se declara como una constante, entonces no se puede modificar: no se puede eliminar nada del conjunto y no se puede agregar nada.

¿Por qué necesitamos Collections.unmodifiableSet ?


Resuma que podemos hacer y no podemos:

Preparación:

private Set<String> words = new HashSet<>(Arrays.asList("existing word"));

Final por referencia

private final Set<String> words = new HashSet<>();

puede :

words.add("new word");

no puedo

words = new HashSet<>(); //compilation error

Final por referencia y no modificable por colección.

Set final privado de palabras = Colecciones.unmodifiableSet (palabras);

puede :

String word = words.iterator().next();

no puedo

words = new HashSet<>(); // compilation error words.add("new word"); // runtime error UnsupportedOperationException

Final por referencia y no modificable por colección pero mutuo como objeto de colección.

Pero si tiene la colección con objetos mutual , puede CAMBIAR el estado interno de ese objeto.

class A { public int a; //mutable field. I can change it after initialization public A(int a) {this.a = a;} } private final Set<A> set = Collections.unmodifiableSet(Arrays.asList(new A(25)));

Todavia no puedo

set = new HashSet<>(); // compilation error set.add(new A(777)); // runtime error UnsupportedOperationException

Pero puede

A custom = words.iterator().next(); //here custom.a = 25; custom.a = 777; //here first element of **final, unmodifible** collection //was changed from 25 to 777


final declara una referencia de objeto que no se puede modificar, por ejemplo,

private final Foo something = new Foo();

Crea un nuevo Foo y coloca la referencia en something . A partir de entonces, no es posible alterar something para señalar una instancia diferente de Foo .

Esto no impide la modificación del estado interno del objeto. Todavía puedo llamar a cualquier método en Foo que esté disponible para el ámbito relevante. Si uno o más de esos métodos modifican el estado interno de ese objeto, entonces final no lo impedirá.

Como tal, lo siguiente:

private final Set<String> fixed = new HashSet<String>();

no crea un Set que no se pueda agregar o modificar de otra manera; solo significa que lo fixed solo hará referencia a esa instancia.

Por el contrario, haciendo:

private Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );

crea una instancia de un Set que lanzará UnsupportedOperationException si uno intenta llamar a fixed.add() o fixed.remove() , por ejemplo: el objeto en sí protegerá su estado interno y evitará que se modifique.

Para la integridad:

private final Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );

crea una instancia de un Set que no permitirá que se cambie su estado interno, y también significa que fixed solo apuntará a una instancia de ese conjunto.

La razón por la que se puede usar final para crear constantes de primitivas se basa en el hecho de que el valor no se puede cambiar. Recuerde que lo anterior fue solo una referencia, una variable que contiene una dirección que no se puede cambiar. Bueno, para primitivos, por ejemplo,

private final int ANSWER = 42;

el valor de ANSWER es 42. Como ANSWER no se puede cambiar, solo tendrá el valor 42.

Un ejemplo que desenfoca todas las líneas sería este:

private final String QUESTION = "The ultimate question";

De acuerdo con las reglas anteriores, la QUESTION contiene la dirección de una instancia de String que representa "La última pregunta", y esa dirección no se puede cambiar. Lo que hay que recordar aquí es que el String sí mismo es inmutable: no se puede hacer nada con una instancia del String que lo cambia, y las operaciones que lo harían (como replace , substring , etc.) devuelven las referencias a diferentes instancias de String .


final no es (estilo C ++) const . A diferencia de C ++, Java no tiene métodos const ni nada de eso, y los métodos que pueden cambiar el objeto se pueden llamar a través de una referencia final .

Collections.unmodifiable* es un contenedor que impone (solo en tiempo de ejecución, no en tiempo de compilación) la capacidad de solo lectura de la colección en cuestión.


final solo garantiza que la referencia al objeto que representa la variable no se puede cambiar, no hace nada por la instancia del objeto y su mutabilidad.

final Set s = new Set(); solo garantiza que no puedes hacer s = new Set(); de nuevo. No hace que el conjunto no sea modificable, si no pudieras agregarle nada para empezar. Entonces, para que quede realmente claro, la final solo afecta a la referencia de variable, no al objeto al que apunta la referencia.

Puedo hacer lo siguiente:

final List<String> l = new ArrayList<String>(); l.add("hello"); l.add("world"); l.remove(0);

pero no puedo hacer esto

l = new ArrayList<String>();

otra vez debido a la final no puedo modificar a qué apunta la variable l.

Tiene que hacer una de las siguientes tres cosas para hacer que un subproceso de contenedor de la colección sea seguro.

java.util.Collections.syncronizedXXX();

o

java.util.Collections.unmodifiableXXX();

o use uno de los contenedores apropiados del java.util.concurrency.* package .

si tuviera un objeto Person y lo hiciera final Person p = new Person("me"); significa que no puedo reasignar p para apuntar a otro objeto Person . Todavía puedo hacer p.setFirstName("you");

Lo que confunde la situación es que

final int PI = 3.14; final String greeting = "Hello World!";

Parecen const en C ++, cuando en realidad los objetos a los que apuntan son inmutables / no modificables por naturaleza. Los contenedores u objetos con métodos de mutación que pueden alterar el estado interno del objeto no son const solo que la referencia a esos objetos es final y no se puede reasignar para hacer referencia a otro objeto.