[英]Convert Map of maps into Lists using Java 8 Streams
我有一张地图:
Map<String, Map<Integer, List<Integer>>>
e.g. Map<Name, Map<Id, List<ReferenceId>>>
Outcome:
List<Id>
List<ReferenceId>
我想将此地图转换为两个整数列表。 一个列表包含内部映射键,另一个列表包含内部映射值(即List<Integer>
)
谁能告诉我如何使用流在Java 8中做到这一点?
我尝试过这种方式,但遇到了Cast Exception,无法将String转换为Integer。
map.values().stream()
.map(m -> m.entrySet()
.stream()
.map(e -> e.getKey())
.collect(Collectors.toList()))
.flatMap(l -> l.stream())
.collect(Collectors.toList());
Map<String, Map<Integer, List<Integer>>> map = ...
List<Integer> keys = map.values() // Collection<Map<Integer, List<Integer>>>
.stream() // Stream<Map<Integer, List<Integer>>>
.map(Map::keySet) // Stream<Set<Integer>>
.flatMap(Set::stream) // Stream<Integer>
.collect(Collectors.toList()); // List<Integer>
List<Integer> values = map.values() // Collection<Map<Integer, List<Integer>>>
.stream() // Stream<Map<Integer, List<Integer>>>
.map(Map::values) // Stream<Collection<List<Integer>>>
.flatMap(Collection::stream) // Stream<List<Integer>>
.flatMap(List::stream) // Stream<Integer>
.collect(Collectors.toList()); // List<Integer>
没办法,你的代码如何
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:unchecked
)并解决它们。
但是请注意,您的代码不必要地复杂。 链.entrySet().stream().map(e -> e.getKey())
在条目上进行流传输并映射到键,因此您可以首先在键上进行流传输,即.keySet().stream()
。 然后,将流收集到List
,只是为了在随后的flatMap
步骤中调用.stream()
,因此您可以简单地使用已有的流来代替:
List<Integer> list = map.values().stream()
.flatMap(m -> m.keySet().stream())
.collect(Collectors.toList());
或者,您可以让收集器完成所有工作:
List<Integer> list = map.values().stream()
.collect(ArrayList::new, (l,m) -> l.addAll(m.keySet()), List::addAll);
获取值而不是键的工作原理类似,但是需要另一个flatMap
步骤来获取List
元素:
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());
同样,也可以让收集器完成所有工作:
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);
如果您的值类似于Map<String,Object>
。 和您的Object
就像Map<String,Object>
:
Set<String> mapKeys = myMap.entryset() //Set<Entry<String,Object>>
.stream() //Stream<Entry<String,Object>>
.map(m->(Map<String,Object>) m.getValue()) //Stream<Map<String,Object>>
.map(Map::keySet) //Stream<Set<String>>
.flatMap(l->l.stream()) //Stream<String>
.collect(Collectors.toSet())
有用
为另一种工作方案添加
Map<Integer, List<Integer>> existingPacakagesMap = // having value {123=[111, 222, 333], 987=[444, 555, 666]}
检索逻辑
List<Integer> ListOfAllPacakages= existingPacakagesMap.values().stream().flatMap(List::stream).collect(Collectors.toList());
结果将是
ListOfAllPacakages = [111、222、333、444、555、666]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.