Javaでマップを反転する方法
1. 概要
この簡単な記事では、Javaでマップを反転する方法を見ていきます。 アイデアは、の新しいインスタンスを作成することです地図
HashMapクラス自体の詳細については、他の記事を参照してください。
2. 問題の定義
いくつかのKey-Valueペアを持つMapがあるとしましょう。
Map<String, Integer> map = new HashMap<>();
map.put("first", 1);
map.put("second", 2);
元のマップには、次のようなアイテムが格納されます。
{first=1, second=2}
代わりに、キーを値に変換し、その逆を新しいMapオブジェクトに変換します。 結果は次のようになります。
{1=first, 2=second}
3. 従来のforループの使用
まず、forループを使用してマップを反転する方法を見てみましょう。
public static <V, K> Map<V, K> invertMapUsingForLoop(Map<K, V> map) {
Map<V, K> inversedMap = new HashMap<V, K>();
for (Entry<K, V> entry : map.entrySet()) {
inversedMap.put(entry.getValue(), entry.getKey());
}
return inversedMap;
}
ここでは、 MapオブジェクトのentrySet()を繰り返し処理しています。 その後、オリジナルを追加します価値新品として鍵とオリジナル鍵新しいものとして価値に reversedMap 物体
4. StreamAPIを使用してマップを反転する
Java 8は、 Stream APIから、より機能的なスタイルでMapを反転するための便利なメソッドを提供します。 それらのいくつかを見てみましょう。
4.1. Collectors.toMap()
ソースマップに重複する値がない場合は、 Collectors.toMap()を使用できます。
public static <V, K> Map<V, K> invertMapUsingStreams(Map<K, V> map) {
Map<V, K> inversedMap = map.entrySet()
.stream()
.collect(Collectors.toMap(Entry::getValue, Entry::getKey));
return inversedMap;
}
まず、 entrySet()がオブジェクトのストリームに変換されます。 続いて、 Collectors.toMap()を使用して、KeyとValueをinversedMapオブジェクトに収集しました。
ソースマップに重複する値が含まれていると考えてみましょう。 このような場合、マッピング関数を使用して、入力要素にカスタムルールを適用できます:
public static <K, V> Map<V, K> invertMapUsingMapper(Map<K, V> sourceMap) {
return sourceMap.entrySet()
.stream().collect(
Collectors.toMap(Entry::getValue, Entry::getKey, (oldValue, newValue) -> oldValue)
);
}
このメソッドでは、 Collectors.toMap()の最後の引数はマッピング関数です。 これを使用して、重複がある場合に追加するキーをカスタマイズできます。 上記の例では、ソースマップに重複する値が含まれている場合、最初の値をキーとして保持します。 ただし、値が繰り返される場合、保持できるキーは1つだけです。
4.2. Collectors.groupingBy()
ソースマップに重複する値が含まれている場合でも、すべてのキーが必要になる場合があります。 または、 Collectors.groupingBy()を使用すると、重複する値を処理するための制御が向上します。
たとえば、次の Key – Valueペアがあるとします。
{first=1, second=2, two=2}
ここでは、値「2」が異なるキーに対して2回繰り返されます。 このような場合、 groupingBy()メソッドを使用して、Valueオブジェクトにカスケードされた「groupby」操作を実装できます。
private static <V, K> Map<V, List<K>> invertMapUsingGroupingBy(Map<K, V> map) {
Map<V, List<K>> inversedMap = map.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
return inversedMap;
}
少し説明すると、 Collectors.mapping()関数は、指定されたコレクターを使用して、指定されたキーに関連付けられた値に対して削減操作を実行します。 groupingBy()コレクターは、重複する値を List に収集し、結果としてMultiMapになります。 出力は次のようになります。
{1=[first], 2=[two, second]}
5. 結論
この記事では、HashMapを反転するためのいくつかの組み込みの方法を例を挙げて簡単に確認しました。 また、Mapオブジェクトを反転するときに重複する値を処理する方法も確認しました。
一方、いくつかの外部ライブラリは、Mapインターフェイスに加えて追加機能を提供します。 以前、 Google GuavaBiMapとApacheBidiMapを使用してMapを反転する方法を示しました。
いつものように、これらの例のコードはGitHubでから入手できます。