如何在 <String><String>Java 8 函数式 API 中将 Map<String、List<List>> 转换为 Map<Stri



我有一个这样的类;

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

现在,我想先按id分组class;

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>>呢?

您可以使用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

就像@ sametey建议你可以使用flatMap.
每当你遇到使用嵌套列表的东西(就像你的Map<String, List<List>>,但有可能在更深的层次上使用它,如Map<String, List<List<List>>>)flatMap将帮助你。

它将把你的流转换成一个单一的扁平流。换句话说:一个可以访问和操作的列表。