1.はじめに


  • このクイックチュートリアルでは、マップから特定の値のキーを取得するための3つの異なるアプローチを紹介します。

    ** また、さまざまなソリューションの長所と短所についても説明します。


Map

インターフェースの詳細については、https://www.baeldung.com/java-hashmap[この記事]を参照してください。

2.反復アプローチ


Java Collections



Map

インタフェースは

entrySet()と呼ばれるメソッドを提供します。

Set__内のマップのすべてのエントリまたはキーと値のペアを返します。

  • このエントリセットを繰り返し処理して、値が指定された値と一致するキーを返すことを考えています。

public <K, V> K getKey(Map<K, V> map, V value) {
    for (Entry<K, V> entry : map.entrySet()) {
        if (entry.getValue().equals(value)) {
            return entry.getKey();
        }
    }
    return null;
}

ただし、複数のキーが同じ値を指している可能性があります。

その場合、一致する値が見つかると、キーを

Set

に追加してループを続行します。最後に、必要なすべてのキーを含む

Set

を返します。

public <K, V> Set<K> getKeys(Map<K, V> map, V value) {
    Set<K> keys = new HashSet<>();
    for (Entry<K, V> entry : map.entrySet()) {
        if (entry.getValue().equals(value)) {
            keys.add(entry.getKey());
        }
    }
    return keys;
}

これは非常に単純な実装ですが、** 数回繰り返した後にすべての一致が見つかった場合でも、すべてのエントリを比較します。

3.機能的アプローチ

  • Java 8でのラムダ式の導入により、より柔軟で読みやすい方法でそれを行うことができます** エントリセットを

    Stream

    に変換し、与えられた値を持つエントリのみをフィルタ処理するためのラムダを提供します。

次に、mapメソッドを使って、フィルタリングされたエントリからキーの

Stream

を返します。

public <K, V> Stream<K> keys(Map<K, V> map, V value) {
    return map
      .entrySet()
      .stream()
      .filter(entry -> value.equals(entry.getValue()))
      .map(Map.Entry::getKey);
}

  • ストリームを返すことの利点は、それが幅広いクライアントのニーズに応えることができるということです。ストリームの評価は遅延するため、クライアントはその要件に基づいて反復回数を制御できます。

さらに、クライアントは適切なコレクターを使用してストリームを任意のコレクションに変換できます。

Stream<String> keyStream1 = keys(capitalCountryMap, "South Africa");
String capital = keyStream1.findFirst().get();

Stream<String> keyStream2 = keys(capitalCountryMap, "South Africa");
Set<String> capitals = keyStream2.collect(Collectors.toSet());

4. Apache Commonsコレクションの使用

上記のアイデアは、特定の地図に対して頻繁に関数を呼び出す必要がある場合には、あまり役に立ちません。それは不必要にそのキーのセットを何度も何度も繰り返すでしょう。

このシナリオでは、

値に対するキーを取得するのに一定の時間がかかるため、

キーへの別の値のマップを維持することはより意味があります。


Apache

による

Commons Collections

ライブラリはhttps://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/BidiMap.html[

BidiMap

]と呼ばれるそのような双方向の

Map

を提供します。

指定された値のキーを取得するための

getKey()

というメソッドがあります。

BidiMap<String, String> capitalCountryMap = new DualHashBidiMap<>();
capitalCountryMap.put("Berlin", "Germany");
capitalCountryMap.put("Cape Town", "South Africa");
String capitalOfGermany = capitalCountryMap.getKey("Germany");

ただし、


BidiMap

は、そのキーと値

の間に1:1の関係を課します。

Mapに値がすでに存在するキーと値のペアを配置しようとすると、

古いエントリが削除されます。つまり、値に対してキーを更新します。

また、リバースマップを保持するためにより多くのメモリが必要です。


BidiMap

の使い方の詳細については、https://www.baeldung.com/commons-collections-bidi-map[このチュートリアル]を参照してください。

5. Google Guavaを使う

  • Googleで開発された


    BiMap


    と呼ばれる別の双方向の

    Map

    を使用することができます。このクラスには、value-key

    Map

    を取得するための

    inverse()

    メソッド、または指定された値に基づいてキーを取得するためのreverse

    Map

    メソッドがあります。

HashBiMap<String, String> capitalCountryMap = HashBiMap.create();
capitalCountryMap.put("Berlin", "Germany");
capitalCountryMap.put("Cape Town", "South Africa");
String capitalOfGermany = capitalCountryMap.inverse().get("Germany");


BidiMap

と同様に、


BiMap

も同じ値を参照する複数のキーを許可しません

。もし私達が____を投げようとしたら

6.まとめ

この短い記事では、値を指定して

Map’s

キーを取得する方法について説明しました。各アプローチには、それぞれ長所と短所があります。ユースケースを常に考慮し、状況に応じて最も適切なものを選択する必要があります。

上記のチュートリアルの完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/java-collections-maps[GitHubで利用可能]です。