2016-12-06 36 views
2

我需要翻轉原始地圖。其類型爲<Integer, String>,如{1 = A, 2 = A, 3 = B....}。我想創建一個新的地圖,這是StringArrayList,因爲如果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

是的,我想我需要迭代一次,並獲得關鍵或值最小。 – 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]}

編輯:如果你想有一個更寬泛的版本,如@ 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

我不會失望,因爲它沒有錯,但我會在codereview上反彈。太難以弄清楚代碼在做什麼,如果你需求改變了,沒有辦法改變它,你必須完全重寫它。 –

+2

這裏一般的共識是,如果Java已經爲某些東西提供了庫/ API,我寧願使用它,而不是編寫自己的樣板代碼(它不會像Java本地API那樣高效)。 –