1. 概要

マップはJavaで最も一般的なデータ構造の1つであり、文字列はマップのキーの最も一般的なタイプの1つです。 デフォルトでは、この種のマップには大文字と小文字が区別されるキーがあります。

この短いチュートリアルでは、文字列のすべての大文字小文字のバリエーションを同じキーとして受け入れるさまざまなマップの実装について説明します。

2. 大文字と小文字を区別しないキーを使用したマップの詳細

解決しようとしている問題をさらに詳しく調べてみましょう。

あるとしましょう地図 1つのエントリで:

次のエントリを追加しましょう:

map.put("ABC", 2);

大文字と小文字を区別するキーを使用してMapを操作すると、次の2つのエントリが作成されます。

ただし、大文字と小文字を区別しないキーを使用して Map を操作する場合、内容は次のようになります。

次の例では、いくつかの一般的な Map 実装の大文字と小文字を区別しない実装について詳しく説明します: TreeMap HashMap 、および LinkedHashMap

3. ツリーマップ

TreeMapNavigableMapの実装です。つまり、指定されたコンパレータに基づいて、挿入後に常にエントリを並べ替えます。 また、 TreeMap は、コンパレータを使用して、挿入されたキーが重複しているか、新しいキーであるかを検出します。

したがって、 大文字と小文字を区別しない文字列コンパレータを提供すると、大文字と小文字を区別しなくなります TreeMap。

幸いなことに、文字列はすでにこの静的コンパレータを提供しています。

public static final Comparator <String> CASE_INSENSITIVE_ORDER

これをコンストラクターで提供できます。

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

そして今、テストを実行すると、マップのサイズが1つであることがわかります。

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(1)の挿入とルックアップを提供するHashMap と比較して、 TreeMapの平均時間O(log n)であることに注意してください。

TreeMapではnullキーが許可されていないことにも注意してください。

4. ApacheのCaseInsensitiveMap

Apache’s Commons-Collections は非常に人気のあるJavaライブラリであり、CaseInsensitiveMapを含む多数の便利なクラスを提供します。

CaseInsensitiveMapはハッシュベースのマップであり、キーを追加または取得する前にキーを小文字に変換します。 ようではない TreeMap CaseInsensitiveMap 許可しますヌルキー挿入。

まず、 commons-collections4依存関係を追加する必要があります。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

これで、 CaseInsensitiveMap を使用して、次の2つのエントリを追加できます。

Map<String, Integer> 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. SpringのLinkedCaseInsensitiveMap

Spring Core は、LinkedCaseInsensitiveMapなどのユーティリティクラスも提供するSpringFrameworkモジュールです。

LinkedCaseInsensitiveMap は、ハッシュテーブルとリンクリストに基づくMapであるLinkedHashMapをラップします。 LinkedHashMap とは異なり、nullキーの挿入は許可されません。 LinkedCaseInsensitiveMapは、元の順序とキーの元の大文字小文字を保持しながら、どのような場合でもgetやremoveなどの関数を呼び出すことができます。

まず、springコア依存関係を追加しましょう。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

これで、新しいLinkedCaseInsensitiveMapを初期化できます。

Map<String, Integer> 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から入手できます。