[英]Java8 streams : Transpose map with values as list
我有鍵作為字符串和值作為列表的映射。 列表可以有 10 個唯一值。 我需要將此映射轉換為鍵為整數,值為列表。 示例如下:
輸入:
“鍵 1”:1,2,3,4
“鍵 2”:2,3,4,5
“鍵 3”:3,4,5,1
預期輸出:
1 : "Key-1","Key-3"
2 : "Key-1","Key-2"
3 : "Key-1", "Key-2", "Key-3"
4 : "Key-1", "Key-2", "Key-3"
5 : "Key-2", "Key-3"
我知道使用 for 循環我可以實現這一點,但我需要知道這可以通過 java8 中的流/lamda 來完成。
-謝謝。
一個想法可能是從原始映射生成所有值鍵對,然后按這些值對鍵進行分組:
import java.util.AbstractMap.SimpleEntry;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
...
Map<Integer, List<String>> transposeMap =
map.entrySet()
.stream()
.flatMap(e -> e.getValue().stream().map(i -> new SimpleEntry<>(i, e.getKey())))
.collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));
Alexis 的回答包含此類任務的一般解決方案,使用flatMap
和一個臨時持有者來組合鍵和扁平值。 避免創建臨時持有者對象的唯一替代方法是重新實現groupingBy
收集器的邏輯並將值列表邏輯上的循環插入到累加器函數中:
Map<Integer, List<String>> mapT = map.entrySet().stream().collect(
HashMap::new,
(m,e) -> e.getValue().forEach(
i -> m.computeIfAbsent(i,x -> new ArrayList<>()).add(e.getKey())),
(m1,m2) -> m2.forEach((k,v) -> m1.merge(k, v, (l1,l2)->{l1.addAll(l2); return l1;})));
這有點可怕(我通常嘗試將其分解以使其更具可讀性)但您可以這樣做:
Map<Integer, List<String>> transposeMap = new HashMap<>();
map.forEach((key, list) -> list.stream().forEach(
elm -> transposeMap.put(elm,
transposeMap.get(elm) == null ? Arrays.asList(key) : (Stream.concat(transposeMap.get(elm).stream(),
Arrays.asList(key).stream()).collect(Collectors.toList())))));
假設Map<String, List<Integer>> map
是您要轉置的原始地圖。 transposeMap
將具有您需要的轉置地圖。
你可以通過這種方式實現
假設我有帶有 Gender 和 Age 的 Person 類。 我想以這種形式得到它
Map<SEX,List<Person>>
我會簡單地寫
Map<SEX,List<Person>> map = personList.stream()
.collect(Collectors.groupingBy(Person::getGender));
它會給我類似下面的東西(一個鍵對多個值)
key:MALE
age31sexMALE
age28sexMALE
key:FEMALE
age40sexFEMALE
age44sexFEMALE
帶teeing
您可以分別處理 2 個流中的鍵和值
從 Java 12 開始
Map<Integer, List<String>> to = from.entrySet().stream()
.collect(teeing(flatMapping(e -> e.getValue().stream(), toList()),
flatMapping(e -> (Stream<String>)e.getValue().stream().map(i -> e.getKey()), toList()),
(k, v) -> {
return IntStream.range(0, k.size()).boxed().collect(
groupingBy(i -> k.get(i), mapping(i -> v.get(i), toList())));
}));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.