2016-12-06 8 views
2

元の地図を反転する必要があります。どのタイプが<Integer, String>であるかは、{1 = A, 2 = A, 3 = B....}です。 からArrayListの新しいマップを作成したいと思います。1 = A2 = Aの場合は、次のようになります。A = [1, 2]Java地図を反転する

どうすればいいですか?

+1

既存のマップを繰り返しますか? – BevynQ

+0

http://stackoverflow.com/questions/3678601/how-to-do-map-inversion-with-guava-with-non-unique-values –

+0

ええ、私は1回繰り返してキーや値を取得する必要があると思います少なくとも。 – Anderson

答えて

3

あなたはこれを試すことができます。

HashMap<Integer, String> original = new HashMap<>(); 
HashMap<String, ArrayList<Integer>> inverted = new HashMap<>(); 

original.put(1, "A"); 
original.put(2, "B"); 
original.put(3, "C"); 
original.put(4, "A"); 

for (Integer key: original.keySet()) { 
    String newKey = original.get(key); 

    inverted.computeIfAbsent(newKey, k -> new ArrayList<>()); 
    inverted.get(newKey).add(key); 

} 
System.out.println(original); 
System.out.println(inverted); 

はそれでは、 HashMap<Integer, String> originalを言わせ {1=A, 2=B, 3=C, 4=A}で、その後、あなたが {A=[1, 4], B=[2], C=[3]}を取得します。

EDIT:あなたが示唆している、@ Mr.Polywhirlなど、より一般的なバージョンを、必要な場合は、使用することができます。

public static final <T, U> Map<U, List<T>> invertMap(Map<T, U> map) { 
    HashMap<U, List<T>> invertedMap = new HashMap<>(); 

    for (T key : map.keySet()) { 
     U newKey = map.get(key); 

     invertedMap.computeIfAbsent(newKey, k -> new ArrayList<>()); 
     invertedMap.get(newKey).add(key); 

    } 

    return invertedMap; 
} 
+0

この問題は(あなたが投稿したオリジナルのバージョンとは対照的に)、これはインデックスごとに2つのハッシュ検索が必要であるということです。あなたのハッシュが例のように自明であれば、大したことはありません。数百のアイテムがある場合は、スピードアップのために別の方法を実行する必要があります。ここに1を超えるべきではありません(computeIfAbsentはアイテムが存在するかどうかを確認する必要があります)。 –

+0

@GabeSechan、このコードをより効率的にするために私の答えを編集してください。私はJavaの知識があまりありません。 – lmiguelvargasf

+0

これは上記のコードの一般的なバージョンです。お気軽にご返信ください。 http://pastebin.com/yTExx5Fi –

4

あなたは簡単に以下の例であり、それは、Java 8のstream APIを使用して行うことができます:

public static void main(String[] args) throws FileNotFoundException { 

    Map<Integer, String> map = new HashMap<>(); 
    map.put(1, "A"); 
    map.put(2, "A"); 
    map.put(3, "B"); 

    Map<String, List<Integer>> invertedMap = map.entrySet() 
    .stream() 
    .collect(Collectors.groupingBy(Entry::getValue, 
      Collectors.mapping(Entry::getKey, Collectors.toList()))); 

    System.out.println(invertedMap); 

} 
+1

私は実際にこのような問題に対してストリーム・アプローチを使用する方が好きな理由を理解できません。これは非直感的な非自己文書化コードのようです。これは伝統的なループの例よりもどのように優れていますか? – bhspencer

+1

私は間違っていないので、downvoteするつもりはありませんが、私はcodereviewでこれをバウンスします。コードが何をしているのか把握するのが難しく、必要な変更があってもそれを変更する方法がない場合は、完全に書き直す必要があります。 –

+2

ここでは、Javaが既に何かのためにライブラリ/ APIを提供しているのであれば、自分自身の定型コードを書くよりも、JavaのネイティブAPIほど効率的ではありません。 –