2017-08-24 30 views
2

我在下面的結構中有一個Map,我想翻轉鍵和值。翻轉鍵,使用Java8流的HashMap中的值

Map<String, List<String>> dataMap 

的樣本數據:

acct01: [aa, ab, ad], 
acct02: [ac, ad] 
acct03: [ax, ab] 

想這個數據轉換爲,

aa: [acct01], 
ab: [acct01, acct03], 
ac: [acct02], 
ad: [acct01, acct02], 
ax: [acct03] 

想知道是否有一個Java 8 - 流方式改變地圖。

我的(不流)

Map<String, List<String>> originalData = new HashMap<String, List<String>>(); 
     originalData.put("Acct01", Arrays.asList("aa", "ab", "ad")); 
     originalData.put("Acct02", Arrays.asList("ac", "ad")); 
     originalData.put("Acct03", Arrays.asList("ax", "ab")); 

     System.out.println(originalData); 
     Map<String, List<String>> newData = new HashMap<String, List<String>>(); 
     originalData.entrySet().forEach(entry -> { 
      entry.getValue().forEach(v -> { 
       if(newData.get(v) == null) { 
        List<String> t = new ArrayList<String>(); 
        t.add(entry.getKey()); 
        newData.put(v, t); 
       } else { 
        newData.get(v).add(entry.getKey()); 
       } 
      }); 
     }); 
     System.out.println(newData); 

輸入和輸出電流的實施, {Acct01=[aa, ab, ad], Acct02=[ac, ad], Acct03=[ax, ab]} {aa=[Acct01], ab=[Acct01, Acct03], ac=[Acct02], ad=[Acct01, Acct02], ax=[Acct03]}

尋找方法來實現使用流。

+0

使用傳統方式實現..仍然在尋找使用Stream()實現的方式 – Bala

回答

3

獲取條目集的流,按照每個鍵值對對齊一個條目,按值分組,將相關鍵收集到列表中。

import static java.util.Arrays.asList; 
import static java.util.stream.Collectors.groupingBy; 
import static java.util.stream.Collectors.mapping; 
import static java.util.stream.Collectors.toList; 

import java.util.AbstractMap.SimpleImmutableEntry; 
import java.util.List; 
import java.util.Map; 
import java.util.Map.Entry; 

<K, V> Map<V, List<K>> invert(Map<K, List<V>> map) { 
    return map.entrySet() 
       .stream() 
       .flatMap(entry -> 
        entry.getValue() 
         .stream() 
         .map(value -> 
          new SimpleImmutableEntry<>(
           entry.getKey(), 
           value 
          ) 
         ) 
      ) 
       .collect(
        groupingBy(
         Entry::getValue, 
         mapping(
          Entry::getKey, 
          toList() 
        ) 
       ) 
      ); 
} 
2

下面是Java的8個流庫中的解決方案:StreamEx

newData = EntryStream.of(originalData).invert().flatMapKeys(k -> k.stream()).grouping(); 
0

您當前已經實現依賴於Java8的功能。在J8中,forEach方法被添加到了許多數據結構中,雖然你可以使用流,但是沒有意義,因爲流的優點來自能夠在懶惰中執行過濾器,排序和其他方法時尚,這不適用於關鍵重新映射。

如果你真的想要,你可以在你的例子中將所有.forEach實例更改爲.stream().forEach,從而在幾個流中分配。

2

如果您願意使用第三方庫(如Eclipse Collections),則可以使用ListMultimap(每個密鑰可以有一個List的值)。 Multimap有flip()。因此,這將工作:

MutableListMultimap<String, String> originalData = Multimaps.mutable.list.empty(); 
originalData.putAll("Acct01", Arrays.asList("aa", "ab", "ad")); 
originalData.putAll("Acct02", Arrays.asList("ac", "ad")); 
originalData.putAll("Acct03", Arrays.asList("ax", "ab")); 
System.out.println(originalData); 

MutableBagMultimap<String, String> newData = originalData.flip(); 
System.out.println(newData); 

輸入:{Acct03=[ax, ab], Acct02=[ac, ad], Acct01=[aa, ab, ad]}

輸出:{ac=[Acct02], ad=[Acct02, Acct01], aa=[Acct01], ab=[Acct03, Acct01], ax=[Acct03]}

請注意,flip()返回BagMultimap每個鍵可以有值的BagBag是無序的特殊數據結構,允許重複。

注意:我是Eclipse集合的提交者。