Implementazioni di mappe immutabili in Java

1. Panoramica

A volte è preferibile non consentire modifiche a java.util.Map come la condivisione di dati di sola lettura tra i thread. A questo scopo, possiamo utilizzare una mappa non modificabile o una mappa immutabile.

In questo rapido tutorial, vedremo qual è la differenza tra loro. Quindi, presenteremo vari modi in cui possiamo creare una mappa immutabile.

2. Non modificabile vs immutabile

Una mappa non modificabile è solo un wrapper su una mappa modificabile e non consente modifiche dirette ad essa:

Map mutableMap = new HashMap(); mutableMap.put("USA", "North America"); Map unmodifiableMap = Collections.unmodifiableMap(mutableMap); assertThrows(UnsupportedOperationException.class, () -> unmodifiableMap.put("Canada", "North America"));

Ma la mappa modificabile sottostante può ancora essere modificata e le modifiche si riflettono anche nella mappa non modificabile:

mutableMap.remove("USA"); assertFalse(unmodifiableMap.containsKey("USA")); mutableMap.put("Mexico", "North America"); assertTrue(unmodifiableMap.containsKey("Mexico"));

Una mappa immutabile, d'altra parte, contiene i propri dati privati ​​e non consente modifiche agli stessi. Pertanto, i dati non possono cambiare in alcun modo una volta creata un'istanza della mappa immutabile.

3. Mappa immutabile di Guava

Guava fornisce versioni immutabili di ogni java.util . Carta geograficautilizzando ImmutableMap . Genera un'eccezione UnsupportedOperationException ogni volta che proviamo a modificarla.

Poiché contiene i propri dati privati, questi dati non cambieranno quando viene modificata la mappa originale.

Discuteremo ora vari modi per creare istanze di ImmutableMap.

3.1. Utilizzo del metodo copyOf ()

Per prima cosa, usiamo il metodo ImmutableMap.copyOf () che restituisce una copia di tutte le voci come nella mappa originale:

ImmutableMap immutableMap = ImmutableMap.copyOf(mutableMap); assertTrue(immutableMap.containsKey("USA"));

Non può essere modificato direttamente o indirettamente:

assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America")); mutableMap.remove("USA"); assertTrue(immutableMap.containsKey("USA")); mutableMap.put("Mexico", "North America"); assertFalse(immutableMap.containsKey("Mexico"));

3.2. Utilizzo del metodo builder ()

Possiamo anche usare il metodo ImmutableMap.builder () per creare una copia di tutte le voci come nella mappa originale.

Inoltre, possiamo utilizzare questo metodo per aggiungere ulteriori voci che non sono presenti nella mappa originale:

ImmutableMap immutableMap = ImmutableMap.builder() .putAll(mutableMap) .put("Costa Rica", "North America") .build(); assertTrue(immutableMap.containsKey("USA")); assertTrue(immutableMap.containsKey("Costa Rica"));

Come nell'esempio precedente, non possiamo modificarlo direttamente o indirettamente:

assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America")); mutableMap.remove("USA"); assertTrue(immutableMap.containsKey("USA")); mutableMap.put("Mexico", "North America"); assertFalse(immutableMap.containsKey("Mexico"));

3.3. Utilizzo del metodo ()

Infine, possiamo utilizzare il metodo ImmutableMap.of () per creare una mappa immutabile con una serie di voci fornite al volo. Supporta al massimo cinque coppie chiave / valore:

ImmutableMap immutableMap = ImmutableMap.of("USA", "North America", "Costa Rica", "North America"); assertTrue(immutableMap.containsKey("USA")); assertTrue(immutableMap.containsKey("Costa Rica"));

Non possiamo modificarlo anche:

assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America"));

4. Conclusione

In questo breve articolo, abbiamo discusso le differenze tra una mappa non modificabile e una mappa immutabile.

Abbiamo anche esaminato diversi modi per creare ImmutableMap di Guava .

E, come sempre, gli esempi di codice completi sono disponibili su GitHub.