如何将嵌套的 Java 集合中的所有项目展平为单个列表? [英] How to flatten all items from a nested Java Collection into a single List?
问题描述
给定一个复杂的嵌套对象集合,例如:
Set>>复杂的嵌套集合;
是否存在通用方法来将其展平并获取包含在其中的所有 Object
的单个 List
?
一些细节:
- 列表不应包含集合对象本身或映射键 - 仅包含最低级别的值.
- 它应该尽可能遵循相同的顺序 - 因此在示例中,列表中的项目将按顺序排列,而映射/集合的顺序将取决于实现.
- 它可以选择性地排除重复项
- 更新:理想情况下,它应该检测/处理任何级别的循环引用,例如一个
List
,其中外部 List 包含自身作为成员.(感谢 Adrian Jałoszewski 在下面的评论中提到这一点).- >
注意:实际用例是从 List
获取所有字符串,这可以通过两个循环轻松完成,但它让我想知道一般情况.>
假设您使用 Java 8,您可以使用 Stream API
感谢方法 flatMap(函数> mapper)
如下:
//1.将Set转换为List
<块引用>
<代码>
返回由替换每个元素的结果组成的流此流的内容与由生成的映射流的内容将提供的映射函数应用于每个元素.每个映射流在其内容放入此流后关闭.(如果映射流为空,则使用空流.)
<小时>
对于 Java
的先前版本,您仍然可以使用 FluentIterable
替换 Stream
并使用 transformAndConcat(Function super E,? extends Iterable extends T>> function)
而不是 flatMap代码> 将您的收藏展平.
之前的代码片段将被重写为下一个:
List
Given a complex nested collection of objects such as:
Set<List<Map<String, List<Object>>>> complexNestedCollection;
Does a generic method exist to flatten this out and get a single List
of all Object
s contained within?
A few details:
- 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).
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.
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> Stream<R> flatMap(Function<? 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.)
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.
The previous code snippet would then be rewritten as next:
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屋!