Карта на Java с нечувствителни към буквите клавиши

1. Общ преглед

Map е една от най-често срещаните структури от данни в Java, а String е един от най-често срещаните типове за ключ на картата. По подразбиране карта от този вид има клавиши, чувствителни към малки и малки букви.

В този кратък урок ще изследваме различни реализации на Map, които приемат всички варианти на случай на String като един и същ ключ .

2. По-внимателен поглед върху картата с чувствителни към регистъра клавиши

Нека разгледаме проблема, който се опитваме да разрешим, по-подробно.

Да предположим, че имаме карта с един запис:

Нека добавим следващия запис:

map.put("ABC", 2);

Когато работим с карта с чувствителни към регистъра ключове, ще получим два записа:

Но когато работите с Карта с нечувствителни към регистъра ключове, съдържанието ще бъде:

В следващите примери ще се потопим в нечувствителни към малки и малки букви реализации на някои популярни реализации на Map : TreeMap , HashMap и LinkedHashMap .

3. TreeMap

TreeMap е реализация на NavigableMap , което означава, че винаги сортира записите след вмъкване въз основа на даден компаратор . Също така TreeMap използва Comparator, за да открие дали вмъкнатият ключ е дубликат или нов.

Следователно, ако осигурим нечувствителен към малки и малки регистър String Comparator , ще получим TreeMap, който не чувствителен към регистъра .

За щастие String вече доставя този статичен компаратор :

public static final Comparator  CASE_INSENSITIVE_ORDER

които можем да предоставим в конструктора:

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

И сега, когато изпълняваме тестове, можем да видим, че размерът на Картата е един:

assertEquals(1, treeMap.size());

и стойността се актуализира до 2:

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

Сега нека премахнем записа, като използваме същия String , но с друг случай:

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

Трябва да имаме предвид, че функции като put и get струват средно време от O (log n) за TreeMap в сравнение с HashMap, което осигурява вмъкване и търсене на O (1).

Също така си струва да се отбележи, че TreeMap не позволява нулеви ключове.

4. CaseInsensitiveMap на Apache

Apache's Commons-Collections е много популярна библиотека на Java, предоставяща голям брой полезни класове с CaseInsensitiveMap сред тях.

CaseInsensitiveMap е базирана на хеш карта , която преобразува ключовете в малки букви, преди да бъдат добавени или извлечени. За разлика от TreeMap , CaseInsensitiveMap позволявавмъкване на нулев ключ.

Първо, трябва да добавим зависимостта commons-collection4 :

 org.apache.commons commons-collections4 4.4 

Сега можем да използваме CaseInsensitiveMap и да добавим два записа:

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

Когато го тестваме, очакваме същите резултати, както видяхме преди:

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 на Spring

Spring Core е модул Spring Framework, който също предоставя класове помощни програми, включително LinkedCaseInsensitiveMap .

LinkedCaseInsensitiveMap обгръща LinkedHashMap , който представлява Карта, базирана на хеш таблица и свързан списък. За разлика от LinkedHashMap , той не позволява вмъкване на нулев ключ. LinkedCaseInsensitiveMap запазва оригиналната поръчка, както и оригиналната обвивка на ключовете, като същевременно позволява извикващи функции като get и remove с всеки случай.

Първо, нека добавим зависимостта spring-core :

 org.springframework spring-core 5.2.5.RELEASE 

Сега можем да инициализираме нова LinkedCaseInsensitiveMap :

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

добавете тествайте го:

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

6. Заключение

В този урок разгледахме различни начини за създаване на Java Map с нечувствителни към регистъра ключове и използвахме различни класове, за да получим това.

Както винаги, кодът е достъпен в GitHub.