如何将嵌套Java集合中的所有项目展平为单个列表? [英] How to flatten all items from a nested Java Collection into a single List?
问题描述
给定一个复杂的嵌套对象集合,例如:
Given a complex nested collection of objects such as:
Set<List<Map<String, List<Object>>>> complexNestedCollection;
是否存在通用方法来平衡这个并获得单个 List
包含在所有对象
中?
Does a generic method exist to flatten this out and get a single List
of all Object
s contained within?
一些细节:
- 该列表不应包含集合对象本身或映射键 - 仅包含最低级别的值。
- 它应尽可能遵循相同的顺序 - 因此在示例中,列表中的项目将按顺序排列,而地图/集合的排序将取决于实现。
- 它可以选择性地排除重复项
- UPDATE:理想情况下,它应检测/处理任何级别的循环引用,例如a
列表< List< Object>>
其中外部List将自身包含为成员。 (感谢AdrianJałoszewski在下面的评论中提到这一点)。
- The list shouldn't include collection objects themselves or map keys - only the values at the lowest level.
- It should follow the same ordering where possible - so in the example, items in the list would be in order, whereas ordering of maps/sets would depend on the implementation.
- It could optionally exclude duplicates
- UPDATE: It should ideally detect/handle circular references at any level, e.g. a
List<List<Object>>
where the outer List contains itself as a member. (Credit to Adrian Jałoszewski for mentioning this in the comments below).
注意:实际用例是获取所有来自列表< List< String>>
的字符串,可以通过两个循环轻松完成,但它让我对一般情况感到疑惑。
Note: The actual use case is to get all Strings from a List<List<String>>
, which can be done easily enough with two loops but it made me wonder about the general case.
推荐答案
假设您使用 Java 8 ,您可以使用 Stream API
感谢方法 flatMap(函数<?super T,?extends Stream<?extends R>> mapper)
作为下一个:
Assuming that you use Java 8, you could do that with the Stream API
thanks to the method flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
as next:
// 1. Convert the Set as a Stream of List<Map<String, List<Object>>>
// 2. Extract the elements of the lists to get a Stream of Map<String, List<Object>>
// 3. Extract values of the maps to get a Stream of List<Object>
// 4. Extract the elements of the lists to get a Stream of Object
// 5. Get rid of duplicates
// 6. Collect the result as a List of Object
List<Object> result = complexNestedCollection.stream()
.flatMap(List::stream)
.flatMap(m -> m.values().stream())
.flatMap(List::stream)
.distinct()
.collect(Collectors.toList());
< R>流< R> flatMap(函数<?super T ,? extends Stream<?extends
R>> mapper)
返回一个包含的流将每个元素
替换为
生成的映射流的内容,将提供的映射函数应用于每个元素。每个映射的
流在其内容放入此流后关闭。
(如果映射的流为空,则使用空流。)
Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)
对于以前的版本 Java
,您仍然可以使用的/releases/snapshot/api/docs/com/google/common/collect/FluentIterable.html\"rel =nofollow noreferrer> FluentIterable
Google Guava 替换 Stream
并使用 transformAndConcat(函数<?super E,?extends Iterable< ?扩展T>>>>>>功能)
而不是 flatMap
来展平您的收藏。
For previous versions of Java
, you can still use FluentIterable
from Google Guava to replace the Stream
and use transformAndConcat(Function<? super E,? extends Iterable<? extends T>> function)
instead of flatMap
to flatten your collection.
之前的代码段将被重写为下一个:
List<Object> result =
new ArrayList<>(
new LinkedHashSet<>(
FluentIterable.from(complexNestedCollection)
.transformAndConcat(
new Function<List<Map<String, List<Object>>>, Iterable<Map<String, List<Object>>>> () {
public Iterable<Map<String, List<Object>>> apply(final List<Map<String, List<Object>>> input) {
return input;
}
}
).transformAndConcat(
new Function<Map<String, List<Object>>, Iterable<List<Object>>> () {
public Iterable<List<Object>> apply(final Map<String, List<Object>> input) {
return input.values();
}
}
).transformAndConcat(
new Function<List<Object>, Iterable<Object>> () {
public Iterable<Object> apply(final List<Object> input) {
return input;
}
}
).toList()
)
);
这篇关于如何将嵌套Java集合中的所有项目展平为单个列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!