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 CollectionsのMapインターフェースは、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 value。 such an attempt, itがjava.lang.IllegalArgumentException. をスローするようにしようとすると
言うまでもなく、BiMapは逆マップを内部に格納する必要があるため、大量のメモリも使用します。 BiMapについて詳しく知りたい場合は、this tutorialを確認してください。
6. 結論
この短い記事では、値を指定してMap’sキーを取得するいくつかの方法について説明しました。 それぞれのアプローチには、長所と短所があります。 ユースケースを常に考慮し、状況に基づいて最も適切なものを選択する必要があります。
上記のチュートリアルの完全なソースコードは、over on GitHubで入手できます。