英文:
How to Convert a Map<String, List<List<String>>> to Map<String, List<String>> in java 8 functional APIs
问题
我有一个这样的类;
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>>>
那么,我如何将Map<String, List<List<String>>>
转换为Map<String, List<String>>
,使用Java 8函数API?
英文:
I have a class like this;
class: {
id: "",
sub: [{
type: 1,
value: ""
}]
}
Now, I want group class first by id;
class.stream().collect(Collectors.groupingBy(class::id))
Then I want flat sub-value to a List<String>
, I have the following:
class.stream().collect(Collectors.groupingBy(class::id,
Collectors.mapping(e ->
e.sub().stream()
.filter(v -> v.type().equals(1))
.map(sub::value),
Collectors.toList()
)))
It returns a Map<String, List<List<String>>>
So, how can I convert a Map<String, List<List<String>>>
to Map<String, List<String>>
using the Java 8 functional API?
答案1
得分: 1
您可以使用Map
收集器按键分组并合并值。
示例(Java 14及以上):
class Test {
// 示例数据类型
record Sub(int type, String value) {}
record Clazz(String id, List<Sub> sub) {}
public static void main(String[] args) {
// 示例数据
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(
// 新地图的键: c.id
c -> c.id,
// 新地图的值: c.sub[].value 作为列表
c -> c.sub.stream().map(s -> s.value).toList(),
// 重复值合并(分组): 合并两个值列表,无重复项
(v1, v2) -> Stream.concat(v1.stream(), v2.stream()).distinct().toList()
));
// 打印生成的数据
map.forEach((k, v) -> System.out.println(k + " -> " + String.join(",", v)));
}
}
输出:
id2 -> C,D
id1 -> A,B,E
英文:
You can use the Map
collector to group by keys and merge the values.
Example (Java 14 & above):
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)));
}
}
Output:
id2 -> C,D
id1 -> A,B,E
答案2
得分: 0
就像@Sametcey建议的那样,您可以使用flatMap
。
每当遇到使用嵌套列表的情况(就像您的Map<String,List<List>>
一样,但也可以在更深层次上使用,如Map<String,List<List<List>>>
),flatMap
会对此进行帮助。
它会将您的流转换为一个单一的扁平流。换句话说:一个可以访问和操作的列表。
英文:
Just like @Sametcey suggested you can use flatMap
.<br> Whenever you encounter something that uses nested lists (just like your Map<String, List<List>>
, but it's possible to use it on deeper level like Map<String, List<List<List>>>
) flatMap
will help you with that.
It will transform your stream into a single flattened stream. In other words: one list that you can access and manipulate.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论