我是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流中以優雅的方式做到這一點?
乾杯, 衛
我是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流中以優雅的方式做到這一點?
乾杯, 衛
假設
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>
實現從Collection
stream()
的事實。其餘的只是把東西塞進正確的地方。
或者,正如@ user140547建議(謝謝),一個更簡單的解決方案
map.forEach((k,v) -> v.forEach(vv -> pam.put(vv, k)));
在上述所有方法中,您推薦哪一種。 – liuwei7923
@ liuwei7923第二個。這是最簡潔和慣用的。另外,你應該升級到最新的Eclipse(霓虹燈)。很可能舊版本在編譯lambda表達式時會出現錯誤。你是兩個主要版本。 –
如果你想不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
。
我嘗試了完全相同的方法。而且Eclipse向我展示了一個編譯錯誤,即「Map.Entry類型沒有定義在此適用的getKey(Object)」。在閱讀你的答案之後,我在google上進行了一些研究,發現它是Luna的一個知識問題,詳細內容在這裏:http://stackoverflow.com/questions/33091946/java-8-stream-flatmap-and-group -by代碼編譯錯誤。升級到火星後,一切工作。謝謝! – liuwei7923
這真是reasy使用免費的StreamEx庫我寫的:
EntryStream.of(map).invert().flatMapKeys(Collection::stream).toMap();
這裏EntryStream.of(map)
產生是由附加操作擴展映射條目的流; invert()
交換密鑰和值,flatMapKeys()
將密鑰保持不變並保留值不變,toMap()
將結果條目收集回地圖。
正如指出的@JimGarrison使用Map.forEach這是很容易
input.forEach((key,value)-> value.forEach(vvalue -> output.put(vvalue, key)));
是一個流*必須*? – ChiefTwoPencils
你有沒有試圖解決這個問題?你試過什麼了? –
@Jim,我嘗試了user149547提供的完全相同的方法。然而,我的月食盧娜拒絕做正確的類型參考,這讓我覺得我錯了。 – liuwei7923