Collezioni immutabili Java

Dalla documentazione di Java 1.6 Collection Framework :

Le raccolte che non supportano alcuna operazione di modifica (come add , remove e clear ) sono considerate non modificabili . […] Le collezioni che garantiscono inoltre che nessuna modifica nell’object Collection sarà mai visibile sono indicate come immutabili .

Il secondo criterio mi confonde un po ‘. Dato che la prima raccolta non è modificabile e supponendo che il riferimento di raccolta originale sia stato eliminato, quali sono le modifiche indicate nella seconda riga? Si riferisce ai cambiamenti negli elementi contenuti nella collezione, vale a dire lo stato degli elementi?

Seconda domanda:
Perché una collezione sia immutabile, come si fa a fornire le garanzie addizionali specificate? Se lo stato di un elemento nella raccolta viene aggiornato da un thread, è sufficiente per l’immutabilità che quegli aggiornamenti nello stato non sono visibili sul thread che contiene la raccolta immutabile?

Perché una collezione sia immutabile, come si fa a fornire le garanzie addizionali specificate?

Le raccolte non modificabili sono in genere viste di sola lettura (wrapper) di altre raccolte. Non è ansible aggiungere, rimuovere o cancellare, ma la raccolta sottostante può cambiare.

Le collezioni immutabili non possono essere cambiate affatto – non avvolgono un’altra collezione – hanno i loro elementi.

Ecco una citazione da ImmutableList di Guava

A differenza di Collections.unmodifiableList(java.util.List) , che è una vista di una collezione separata che può ancora cambiare, un’istanza di ImmutableList contiene i propri dati privati ​​e non cambierà mai.

Quindi, in sostanza, per ottenere una collezione immutabile da una mutevole, devi copiare i suoi elementi nella nuova raccolta e non consentire tutte le operazioni.

La differenza è che non puoi avere un riferimento a una collezione immutabile che consente modifiche. Le collezioni non modificabili non sono modificabili attraverso quel riferimento , ma alcuni altri oggetti potrebbero puntare agli stessi dati attraverso i quali può essere modificato.

per esempio

 List strings = new ArrayList(); List unmodifiable = Collections.unmodifiableList(strings); unmodifiable.add("New string"); // will fail at runtime strings.add("Aha!"); // will succeed System.out.println(unmodifiable); 
 Collection c1 = new ArrayList(); c1.add("foo"); Collection c2 = Collections.unmodifiableList(c1); 

c1 è mutabile (cioè né immodificabileimmodificabile ).
c2 è immodificabile : non può essere modificato da solo, ma se in seguito cambio c1 quel cambiamento sarà visibile in c2 .

Questo perché c2 è semplicemente un wrapper attorno a c1 e non è davvero una copia indipendente. Guava fornisce l’ interfaccia ImmutableList e alcune implementazioni. Questi funzionano creando effettivamente una copia dell’input (a meno che l’input non sia una collezione immutabile).

Per quanto riguarda la tua seconda domanda:

La mutabilità / immutabilità di una collezione non dipende dalla mutevolezza / immutabilità degli oggetti in essa contenuti. La modifica di un object contenuto in una raccolta non è considerata una “modifica della raccolta” per questa descrizione. Naturalmente se hai bisogno di una collezione immutabile, di solito vuoi anche che contenga oggetti immutabili.

Ora java 9 ha i metodi di fabbrica per Immutable List, Set, Map e Map.Entry.

In Java SE 8 e versioni precedenti, possiamo utilizzare i metodi di utilità della class Collections come UnmodifiableXXX per creare oggetti Collezione immutabili.

Tuttavia questi metodi Collections.unmodifiableXXX sono un approccio molto noioso e prolisso. Per superare queste carenze, Oracle Corp ha aggiunto un paio di metodi di utilità alle interfacce List, Set e Map.

Ora in Java 9: ​​- Le interfacce Elenco e Set hanno metodi “di ()” per creare un elenco immutabile vuoto o non vuoto o impostare oggetti come mostrato di seguito:

Esempio di lista vuota

 List immutableList = List.of(); 

Esempio di elenco non vuoto

 List immutableList = List.of("one","two","three"); 

Credo che il punto qui sia che anche se una collezione è non modificabile, ciò non garantisce che non possa cambiare. Prendiamo ad esempio una collezione che elude gli elementi se sono troppo vecchi. Immodificabile significa semplicemente che l’object che detiene il riferimento non può cambiarlo, non che non può cambiare. Un vero esempio di ciò è il metodo Collections.unmodifiableList . Restituisce una vista non modificabile di un elenco. Il riferimento a Elenco passato a questo metodo è ancora modificabile e quindi l’elenco può essere modificato da qualsiasi titolare del riferimento che è stato passato. Ciò può causare ConcurrentModificationExceptions e altre cose negative.

Immutabile, significa che in nessun modo la collezione può essere cambiata.

Seconda domanda: una collezione Immutable non significa che gli oggetti contenuti nella collezione non cambieranno, solo che la collezione non cambierà nel numero e nella composizione degli oggetti che contiene. In altre parole, la lista dei riferimenti della collezione non cambierà. Ciò non significa che le parti interne dell’object a cui si fa riferimento non possano cambiare.

Pure4J supporta ciò che stai cercando , in due modi.

Innanzitutto, fornisce un’annotazione @ImmutableValue , in modo che tu possa annotare una class per dire che è immutabile. C’è un plugin di Maven per permetterti di controllare che il tuo codice sia effettivamente immutabile (uso del final ecc.).

In secondo luogo, fornisce le collezioni persistenti di Clojure, (con generici aggiunti) e assicura che gli elementi aggiunti alle raccolte siano immutabili. Le prestazioni di questi sono apparentemente piuttosto buone. Le raccolte sono tutte immutabili, ma implementano interfacce di raccolte java (e generici) per l’ispezione. La mutazione restituisce nuove collezioni.

Disclaimer: sono lo sviluppatore di questo