1. Обзор
Map – одна из наиболее распространенных структур данных в Java, а String – один из наиболее распространенных типов ключа карты. По умолчанию карта такого рода имеет ключи, чувствительные к регистру.
В этом коротком уроке мы рассмотрим различные реализации Map , которые принимают все варианты Строки в качестве одного и того же ключа .
2. Более пристальный взгляд на карту с ключами без учета регистра
Давайте рассмотрим проблему, которую мы пытаемся решить более подробно.
Предположим, у нас есть Map Integer> с одной записью: Integer>
Давайте добавим следующую запись:
map.put("ABC", 2);
При работе с картой с ключами, чувствительными к регистру, мы получим две записи:
Но при работе с Map с ключами без учета регистра содержимое будет:
В следующих примерах мы погрузимся в нечувствительные к регистру реализации некоторых популярных реализаций Map : TreeMap , HashMap и LinkedHashMap .
3. Карта деревьев
TreeMap является реализацией NavigableMap , что означает, что он всегда сортирует записи после вставки на основе заданного компаратора . Кроме того, TreeMap использует Компаратор , чтобы определить, является ли вставленный ключ дубликатом или новым.
Поэтому, если мы предоставим нечувствительный к регистру Строку Компаратор , мы получим нечувствительную к регистру древовидную карту .
К счастью, String уже предоставляет этот статический Компаратор :
public static final ComparatorCASE_INSENSITIVE_ORDER
которые мы можем предоставить в конструкторе:
MaptreeMap = 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());
Теперь давайте удалим запись, используя ту же строку , но в другом случае:
treeMap.remove("aBC"); assertEquals(0, treeMap.size());
Мы должны иметь в виду, что функции, такие как put и get , стоят среднего времени O(log n) для TreeMap по сравнению с хэш-картой , которая обеспечивает вставку и поиск O(1).
Также стоит отметить, что TreeMap не допускает null ключей.
4. CaseInsensitiveMap Apache
Apache Commons-Collections – очень популярная библиотека Java, предоставляющая большое количество полезных классов с CaseInsensitiveMap среди них.
CaseInsensitiveMap -это карта на основе хэша , которая преобразует ключи в нижний регистр перед их добавлением или извлечением. В отличие от TreeMap , CaseInsensitiveMap позволяет null вставку ключа.
Во-первых, нам нужно добавить | commons-collections4 зависимость :
org.apache.commons commons-collections4 4.4
Теперь мы можем использовать CaseInsensitiveMap и добавить две записи:
MapcommonsHashMap = 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 , он не позволяет вставлять null ключ. LinkedCaseInsensitiveMap сохраняет исходный порядок, а также исходный корпус ключей, позволяя вызывать такие функции, как get и remove в любом случае.
Во-первых, давайте добавим spring-core зависимость :
org.springframework spring-core 5.2.5.RELEASE
Теперь мы можем инициализировать новую LinkedCaseInsensitiveMap :
MaplinkedHashMap = 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 .