Javaマップから値のキーを取得する

Javaマップから値のキーを取得する

 

1. 前書き

In this quick tutorial, we’re going to demonstrate three different approaches for retrieving the key from a map for a given value. さまざまなソリューションの長所と短所についても説明します。

Mapインターフェースの詳細については、this articleを確認してください。

2. 反復アプローチ

Java CollectionsMapインターフェースは、entrySet()と呼ばれるメソッドを提供します。 マップのすべてのエントリまたはキーと値のペアをSetで返します。

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

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

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

その場合、一致する値が見つかった場合は、キーをSetに追加して、ループを続行します。 最後に、必要なすべてのキーを含むSetを返します。

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

これは非常に単純な実装ですが、it compares all the entries even if all matches are found after a few iterations.

3. 機能的アプローチ

With the introduction of Lambda Expressions in Java 8, we can do it in a more flexible and readable way.エントリセットをStreamに変換し、ラムダを指定して、指定された値を持つエントリのみをフィルタリングします。

次に、mapメソッドを使用して、フィルタリングされたエントリからキーのStreamを返します。

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

The advantage of returning a stream is that it can cater to a wide range of client needs.呼び出し元のコードには、指定された値を指す1つのキーのみまたはすべてのキーが必要な場合があります。 ストリームの評価が遅延しているため、クライアントは要件に基づいて反復回数を制御できます。

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

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

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

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

上記のアイデアは、if we need to call the functions very frequently for a particular mapにはあまり役立ちません。 キーのセットを繰り返し不必要に反復します。

このシナリオでは、maintaining another map of value to the keys would make more sense as it will take constant time to retrieve the key for a value.

ApacheによるCommons Collectionsライブラリは、BidiMapと呼ばれるそのような双方向のMapを提供します。 指定された値のキーを取得するためのgetKey()という名前のメソッドがあります。

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

ただし、BidiMap imposes a 1:1 relationship between its keys and values。 値がMap,にすでに存在するキーと値のペアを配置しようとすると、古いエントリが削除されます。 つまり、値に対してキーを更新します。

また、逆マップを保持するには大量のメモリが必要です。

BidiMapの使用方法の詳細は、this tutorialにあります。

5. Google Guavaを使用する

We may use another bi-directional Map called BiMap found in Guava developed by Google.このクラスは、値キーMapを取得するためのinverse()という名前のメソッド、または指定された値に基づいてキーをフェッチするための逆Mapを提供します。

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

BidiMapと同様に、BiMap also doesn’t allow multiple keys referring to the same valuesuch an attempt, itjava.lang.IllegalArgumentException. をスローするようにしようとすると

言うまでもなく、BiMapは逆マップを内部に格納する必要があるため、大量のメモリも使用します。 BiMapについて詳しく知りたい場合は、this tutorialを確認してください。

6. 結論

この短い記事では、値を指定してMap’sキーを取得するいくつかの方法について説明しました。 それぞれのアプローチには、長所と短所があります。 ユースケースを常に考慮し、状況に基づいて最も適切なものを選択する必要があります。

上記のチュートリアルの完全なソースコードは、over on GitHubで入手できます。