Java Map con tasti senza distinzione tra maiuscole e minuscole

1. Panoramica

Map è una delle strutture dati più comuni in Java e String è uno dei tipi più comuni per la chiave di una mappa. Per impostazione predefinita, una mappa di questo tipo ha chiavi che fanno distinzione tra maiuscole e minuscole.

In questo breve tutorial, esploreremo diverse implementazioni di mappe che accettano tutte le variazioni di maiuscole e minuscole di una stringa come la stessa chiave .

2. Uno sguardo più da vicino alla mappa con tasti senza distinzione tra maiuscole e minuscole

Esaminiamo il problema che stiamo cercando di risolvere in modo più dettagliato.

Supponiamo di avere una mappa con una voce:

Aggiungiamo la voce successiva:

map.put("ABC", 2);

Quando lavoriamo con una mappa con chiavi che fanno distinzione tra maiuscole e minuscole, avremo due voci:

Ma quando si lavora con una mappa con chiavi senza distinzione tra maiuscole e minuscole, il contenuto sarà:

Nei prossimi esempi, ci immergeremo nelle implementazioni senza distinzione tra maiuscole e minuscole di alcune implementazioni di mappe popolari : TreeMap , HashMap e LinkedHashMap .

3. TreeMap

TreeMap è un'implementazione di NavigableMap , il che significa che ordina sempre le voci dopo l'inserimento, in base a un dato Comparator . Inoltre, TreeMap utilizza un comparatore per scoprire se una chiave inserita è duplicata o nuova.

Pertanto, se forniamo un comparatore di stringhe senza distinzione tra maiuscole e minuscole , otterremo una TreeMap senza distinzione tra maiuscole e minuscole .

Fortunatamente, String fornisce già questo comparatore statico :

public static final Comparator  CASE_INSENSITIVE_ORDER

che possiamo fornire nel costruttore:

Map treeMap = new TreeMap(String.CASE_INSENSITIVE_ORDER); treeMap.put("abc", 1); treeMap.put("ABC", 2);

E ora, quando eseguiamo i test, possiamo vedere che la dimensione della mappa è una:

assertEquals(1, treeMap.size());

e il valore viene aggiornato a 2:

assertEquals(2, treeMap.get("aBc").intValue()); assertEquals(2, treeMap.get("ABc").intValue());

Ora rimuoviamo la voce, usando la stessa stringa , ma con un altro caso:

treeMap.remove("aBC"); assertEquals(0, treeMap.size());

Dobbiamo tenere presente che funzioni come put e get costano un tempo medio di O (log n) per la TreeMap rispetto a una HashMap che fornisce l'inserimento e la ricerca di O (1).

Vale anche la pena notare che TreeMap non consente chiavi null .

4. CaseInsensitiveMap di Apache

Le Commons-Collections di Apache sono una libreria Java molto popolare, che fornisce un gran numero di classi utili tra cui CaseInsensitiveMap .

CaseInsensitiveMap è una mappa basata su hash , che converte le chiavi in lettere minuscole prima che vengano aggiunte o recuperate. A differenza di TreeMap , CaseInsensitiveMap consente l' inserimento di chiavi null .

Innanzitutto, dobbiamo aggiungere la dipendenza commons-collections4 :

 org.apache.commons commons-collections4 4.4 

Ora possiamo usare CaseInsensitiveMap e aggiungere due voci:

Map commonsHashMap = new CaseInsensitiveMap(); commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2);

Quando lo testiamo, ci aspettiamo gli stessi risultati visti in precedenza:

assertEquals(1, commonsHashMap.size()); assertEquals(2, commonsHashMap.get("aBc").intValue()); assertEquals(2, commonsHashMap.get("ABc").intValue()); commonsHashMap.remove("aBC"); assertEquals(0, commonsHashMap.size());

5. LinkedCaseInsensitiveMap di Spring

Spring Core è un modulo Spring Framework che fornisce anche classi di utilità, tra cui LinkedCaseInsensitiveMap .

LinkedCaseInsensitiveMap racchiude un LinkedHashMap , che è una mappa basata su una tabella hash e un elenco collegato. A differenza di LinkedHashMap , non consente l' inserimento di chiavi null . LinkedCaseInsensitiveMap conserva l'ordine originale e l'involucro originale delle chiavi, consentendo al contempo di chiamare funzioni come get e remove con qualsiasi case.

Innanzitutto, aggiungiamo la dipendenza spring-core :

 org.springframework spring-core 5.2.5.RELEASE 

Ora possiamo inizializzare una nuova LinkedCaseInsensitiveMap :

Map linkedHashMap = new LinkedCaseInsensitiveMap(); linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2);

aggiungi testalo:

assertEquals(1, linkedHashMap.size()); assertEquals(2, linkedHashMap.get("aBc").intValue()); assertEquals(2, linkedHashMap.get("ABc").intValue()); linkedHashMap.remove("aBC"); assertEquals(0, linkedHashMap.size());

6. Conclusione

In questo tutorial, abbiamo esaminato diversi modi per creare una mappa Java con chiavi senza distinzione tra maiuscole e minuscole e abbiamo utilizzato classi diverse per ottenerlo.

Come sempre, il codice è disponibile su GitHub.