问题描述
我有一张地图:
Map<String, Map<Integer, List<Integer>>>
e.g. Map<Name, Map<Id, List<ReferenceId>>>
Outcome:
List<Id>
List<ReferenceId>
我想将此地图转换为两个整数列表。一个列表包含内部映射键,另一个列表包含内部映射值(即列表<整数>
)
I wanna convert this map into two list of Integers. One list contains inner-map keys, and other contains inner-map value (i.e. List<Integer>
)
任何人都可以告诉我如何使用流在Java 8中执行此操作?
Can anyone tell me how to do this in Java 8 using streams?
我试过这种方式但得到了Cast Exception,无法将String转换为Integer。
I tried this way but got Cast Exception, can not convert String to Integer.
map.values().stream()
.map(m -> m.entrySet()
.stream()
.map(e -> e.getKey())
.collect(Collectors.toList()))
.flatMap(l -> l.stream())
.collect(Collectors.toList());
推荐答案
没有办法,你的代码如何
There is no way, how your code
List<Integer> list = map.values().stream()
.map(m -> m.entrySet().stream()
.map(e -> e.getKey())
.collect(Collectors.toList()))
.flatMap(l -> l.stream())
.collect(Collectors.toList());
可以产生 ClassCastException
,除非你管理在 Stream操作之前,通过未经检查的操作将错误类型的对象插入到源映射中。这种情况称为堆污染,您应该在启用所有警告的情况下编译整个代码( javac
:使用选项 - Xlint:未经检查
)并解决它们。
can produce a ClassCastException
, unless you managed to insert objects of wrong type into the source map via unchecked operation(s) before the Stream operation. Such a situation is called heap pollution and you should compile your entire code with all warnings enabled (javac
: use option -Xlint:unchecked
) and solve them.
但请注意,您的代码不必要地复杂化。链, .entrySet()。stream()。map(e - > e.getKey())
是在条目上流式传输并映射到键,所以你可以首先流式传输密钥,即 .keySet()。stream()
。然后,您将流收集到 List
中,只是为了在次要的<$ c中调用 .stream()
$ c> flatMap 步骤,因此您只需使用您已有的流:
But note that your code is unnecessarily complicated. The chain, .entrySet().stream().map(e -> e.getKey())
is streaming over the entries and mapping to the keys, so you can stream over the keys in the first place, i.e. .keySet().stream()
. Then, you are collecting the stream into a List
, just to invoke .stream()
in the subequent flatMap
step, so you can simply use the stream you already have instead:
List<Integer> list = map.values().stream()
.flatMap(m -> m.keySet().stream())
.collect(Collectors.toList());
或者,您可以让收藏家完成所有工作:
Alternatively, you can let the collector do all the work:
List<Integer> list = map.values().stream()
.collect(ArrayList::new, (l,m) -> l.addAll(m.keySet()), List::addAll);
获取值而不是键的工作方式类似,但需要另一个 flatMap
步骤获取列表
元素:
Getting the values instead of the keys works similar, but requires another flatMap
step to get the List
elements:
List<Integer> list = map.values().stream()
.flatMap(m -> m.values().stream().flatMap(List::stream))
.collect(Collectors.toList());
相当于
List<Integer> list = map.values().stream()
.flatMap(m -> m.values().stream())
.flatMap(List::stream)
.collect(Collectors.toList());
同样,还有让收藏家完成所有工作的替代方案:
Again, there’s the alternative of letting the collector do all the work:
List<Integer> list = map.values().stream()
.collect(ArrayList::new, (l,m)->m.values().forEach(l::addAll), List::addAll);
或
List<Integer> list = map.values().stream()
.collect(ArrayList::new, (l,m)->m.forEach((k,v)->l.addAll(v)), List::addAll);
这篇关于使用Java 8 Streams将地图映射转换为列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!