2016-09-17 60 views
3

我是Java8的新手。我想解決的問題是使用Stream將Map>轉換爲Map。例如:Java8:如何轉換地圖<X, List<Y>>到地圖<Y,X>使用流?

input: {A => [B, C, D], E => [F]} 
output: {B => A, C => A, D => A, F => E} 

我們假設列表中沒有重複值。如何在java 8流中以優雅的方式做到這一點?

乾杯, 衛

+0

是一個流*必須*? – ChiefTwoPencils

+0

你有沒有試圖解決這個問題?你試過什麼了? –

+0

@Jim,我嘗試了user149547提供的完全相同的方法。然而,我的月食盧娜拒絕做正確的類型參考,這讓我覺得我錯了。 – liuwei7923

回答

2

假設

Map<String, List<Integer>> map = new HashMap<>(); 
    Map<Integer,String>  pam = new HashMap<>(); 

這會做你想要

map.entrySet().stream().forEach(e -> e.getValue().stream().forEach(v -> pam.put(v, e.getKey()))); 

什麼這需要的是Set<E>實現從Collectionstream()的事實。其餘的只是把東西塞進正確的地方。

或者,正如@ user140547建議(謝謝),一個更簡單的解決方案

map.forEach((k,v) -> v.forEach(vv -> pam.put(vv, k))); 
+0

在上述所有方法中,您推薦哪一種。 – liuwei7923

+0

@ liuwei7923第二個。這是最簡潔和慣用的。另外,你應該升級到最新的Eclipse(霓虹燈)。很可能舊版本在編譯lambda表達式時會出現錯誤。你是兩個主要版本。 –

4

如果你想不forEach()的解決方案,你可以這樣做:

Map<Integer, String> pam = 
      map.entrySet().stream() 
      .flatMap(x -> x.getValue().stream().map(v -> new AbstractMap.SimpleEntry<>(v, x.getKey()))) 
      .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 

每個條目像"3"-> [3,4,5,6]3->3,4->3,5->3,6->3創建一個條目流,使用flatMap它可以被平化爲一個流,然後Collectors.toMap()創建最終Map

+0

我嘗試了完全相同的方法。而且Eclipse向我展示了一個編譯錯誤,即「Map.Entry類型沒有定義在此適用的getKey(Object)」。在閱讀你的答案之後,我在google上進行了一些研究,發現它是Luna的一個知識問題,詳細內容在這裏:http://stackoverflow.com/questions/33091946/java-8-stream-flatmap-and-group -by代碼編譯錯誤。升級到火星後,一切工作。謝謝! – liuwei7923

3

這真是reasy使用免費的StreamEx庫我寫的:

EntryStream.of(map).invert().flatMapKeys(Collection::stream).toMap(); 

這裏EntryStream.of(map)產生是由附加操作擴展映射條目的流; invert()交換密鑰和值,flatMapKeys()將密鑰保持不變並保留值不變,toMap()將結果條目收集回地圖。

0

正如指出的@JimGarrison使用Map.forEach這是很容易

input.forEach((key,value)-> value.forEach(vvalue -> output.put(vvalue, key))); 
相關問題