簡體   English   中英

Java8流:將值作為列表轉置映射

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM