如何在java 8函数式API中将Map〈String,List〈List< String>>>转换为Map〈String,List< String>>

sqyvllje  于 2023-04-10  发布在  Java
关注(0)|答案(3)|浏览(240)

我有一门这样的课;

class: {
   id: "",
   sub: [{
       type: 1,
       value: ""
   }]
}

现在,我希望组类首先由id;

class.stream().collect(Collectors.groupingBy(class::id))

然后我需要一个List<String>的平面子值,我有以下内容:

class.stream().collect(Collectors.groupingBy(class::id,
  Collectors.mapping(e ->
    e.sub().stream()
      .filter(v -> v.type().equals(1))
       .map(sub::value),
    Collectors.toList()
  )))

它返回一个Map<String, List<List<String>>>
那么,如何使用Java 8函数式API将Map<String, List<List<String>>>转换为Map<String, List<String>>呢?

h43kikqp

h43kikqp1#

要使用Java 8函数API将Map〈String,List〉转换为Map〈String,List〉,可以使用flatMap方法沿着Stream和Collectors.toMap()。
下面是一个例子:

Map<String, List<List<String>>> mapOfLists = new HashMap<>();
// add some data to the mapOfLists

    Map<String, List<String>> flattenedMap =
        mapOfLists.entrySet().stream()
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> entry.getValue().stream()
                          .flatMap(Collection::stream)
                          .collect(Collectors.toList())));

在本例中,我们首先使用entrySet()方法获取Map.Entry〈String,List〉流。然后使用Collectors.toMap()方法创建新的Map〈String,List〉。
Collectors.toMap()的第一个参数指定如何从原始Map中Map键,我们只需使用Map.Entry::getKey从条目中获取键。第二个参数指定如何从原始Map中Map值。
对于原始map中的每个条目,我们使用entry.getValue().stream()获取所有内部列表的流。然后使用flatMap(Collection::stream)将每个内部列表扁平化为单个String流。最后,使用Collectors.toList()将所有String元素收集到一个新列表中。

8zzbczxx

8zzbczxx2#

您可以使用Map收集器按键分组并合并值。
示例(Java 14及以上):

class Test {

    // sample data types
    record Sub ( int type, String value ){}
    record Clazz (String id, List<Sub> sub){}

    public static void main(String[] args)
    {
        // sample data
        List<Clazz> classes = List.of(
            new Clazz("id1",List.of(new Sub(1,"A"),new Sub(2,"B"))),
            new Clazz("id2",List.of(new Sub(3,"C"),new Sub(4,"D"))),
            new Clazz("id1",List.of(new Sub(5,"E"),new Sub(6,"A")))
        );

        Map<String, List<String>> map = classes.stream()
            .collect(Collectors.toMap(
                // key for new map: c.id
                c -> c.id,
                
                // value for new map: c.sub[].value as a list
                c -> c.sub.stream().map(s -> s.value).toList(),
                
                // duplicate value merging (grouping) : merge two value lists, no duplicates
                (v1, v2) -> Stream.concat(v1.stream(), v2.stream()).distinct().toList()
            ));

        // print resulting data
        map.forEach((k,v) -> System.out.println(k + "\t->\t" + String.join(",", v)));
    }
}

输出:

id2 ->  C,D
id1 ->  A,B,E
relj7zay

relj7zay3#

就像@Sametcey建议的那样,你可以使用flatMap
无论何时你遇到使用嵌套列表的东西(就像你的Map<String, List<List>>,但是可以在更深的层次上使用它,比如Map<String, List<List<List>>>),flatMap都会帮助你。
它会将您的流转换为单个扁平流。换句话说:一个你可以访问和操作的列表。

相关问题