如何将嵌套的 Java 集合中的所有项目展平为单个列表? [英] How to flatten all items from a nested Java Collection into a single List?

查看:49
本文介绍了如何将嵌套的 Java 集合中的所有项目展平为单个列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个复杂的嵌套对象集合,例如:

Set>>复杂的嵌套集合;

是否存在通用方法来将其展平并获取包含在其中的所有 Object 的单个 List?

一些细节:

  1. 列表不应包含集合对象本身或映射键 - 仅包含最低级别的值.
  2. 它应该尽可能遵循相同的顺序 - 因此在示例中,列表中的项目将按顺序排列,而映射/集合的顺序将取决于实现.
  3. 它可以选择性地排除重复项
  4. 更新:理想情况下,它应该检测/处理任何级别的循环引用,例如一个 List>,其中外部 List 包含自身作为成员.(感谢 Adrian Jałoszewski 在下面的评论中提到这一点).

注意:实际用例是从 List> 获取所有字符串,这可以通过两个循环轻松完成,但它让我想知道一般情况.

解决方案

假设您使用 Java 8,您可以使用 Stream API 感谢方法 flatMap(函数> mapper) 如下:

//1.将Set转换为List>的Stream//2.提取列表的元素,得到一个Stream of Map>//3. 提取maps的值,得到List的Stream//4. 提取列表的元素,得到一个 Stream of Object//5. 去除重复//6. 将结果收集为对象列表列表<对象>结果 = complexNestedCollection.stream().flatMap(列表::流).flatMap(m -> m.values().stream()).flatMap(列表::流).清楚的().collect(Collectors.toList());

<块引用>

<代码>Stream <R>flatMap(Function

返回由替换每个元素的结果组成的流此流的内容与由生成的映射流的内容将提供的映射函数应用于每个元素.每个映射流在其内容放入此流后关闭.(如果映射流为空,则使用空流.)

<小时>

对于 Java先前版本,您仍然可以使用 FluentIterable 替换 Stream 并使用 transformAndConcat(Function> function) 而不是 flatMap 将您的收藏展平.

之前的代码片段将被重写为下一个:

List结果 =新的 ArrayList<>(新的 LinkedHashSet<>(FluentIterable.from(complexNestedCollection).transformAndConcat(new Function>, Iterable>>(){public Iterable<Map<String, List<Object>>>应用(最终列表<地图<字符串,列表<对象>>输入){返回输入;}}).transformAndConcat(new Function<Map<String, List<Object>>, Iterable<List<Object>>(){public Iterable>应用(最终地图<字符串,列表<对象>>输入){返回 input.values();}}).transformAndConcat(new Function, Iterable>(){public Iterable应用(最终列表<对象>输入){返回输入;}}).toList()));

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 Objects contained within?

A few details:

  1. The list shouldn't include collection objects themselves or map keys - only the values at the lowest level.
  2. 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.
  3. It could optionally exclude duplicates
  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆