【问题标题】:Using streams to group Map attributes from inner objects?使用流对内部对象的 Map 属性进行分组?
【发布时间】:2019-06-12 19:12:34
【问题描述】:

我正在学习 Java 8 - Java 11,我得到了一个要转换为 的代码。我有以下课程:

class Resource {
   List<Capability> capabilities;
}

class Capability {
   String namespace;
   Map<String, Object> attributes;
}

我有一个资源流,我想从两个不同的命名空间(“a”、“b”)中提取其所有功能属性到我确定没有重复键的 Map&lt;Resource, Map&lt;String, Object&gt;&gt;

我使用 map、flatMap 做了很多尝试,但使用这些,我无法保留对主要资源对象的引用。使用 java9 的新功能我可以进步,但我被困在下面的代码中,我能够返回所有属性,但是在一个集合中。 我还不能按功能命名空间过滤并将它们放在地图中:

Map<Resource, Set<Object>> result = pResolved.stream()
    .collect(groupingBy(t -> t, flatMapping(
            resource -> resource.getCapabilities(null).stream(),
            flatMapping(
                    cap -> cap.getAttributes().entrySet().stream(),
                    toSet()))));

看来我是在正确的道路上。

【问题讨论】:

    标签: java-streams java collections java-8 java-stream java-11


    【解决方案1】:

    还有一种方法只使用 方法:

    Map<String, Set<Object>> result = pResolved.stream()                        
        .map(Resource::getCapabilities)                         // Stream<List<Capability>>
        .flatMap(List::stream)                                  // Stream<Capability>
        .collect(Collectors.toMap(                              // Map<String, Set<Object>>
            c -> c.getNamespace(),                              // Key: String (namespace)
            i -> new HashSet<>(i.getAttributes().values())));   // Value: Set of Map values
    

    假设样本输入是:

    Resource [capabilities=[
        Capability [namespace=a, attributes={a1=aa1, a2=aa2, a3=aa3}]]]
    Resource [capabilities=[
        Capability [namespace=b, attributes={b2=bb2, b3=bb3, b1=bb1}], 
        Capability [namespace=c, attributes={c3=cc3, c1=cc1, c2=cc2}]]]
    

    那么上面的代码会导致:

    a: [aa1, aa3, aa2]
    b: [bb1, bb3, bb2]
    c: [cc1, cc3, cc2]
    

    【讨论】:

    • 嗨 Nicolas,但使用 java-8 的问题是我在执行第一个 .map() 时丢失了资源对象的引用。我需要一个 Map。感谢您编辑问题。
    【解决方案2】:

    您可以改用Collectors.toMap 作为downstream

    Map<Resource, Map<String, Object>> result = pResolved
            .stream()
            .collect(groupingBy(Function.identity(),
                    flatMapping(resource -> resource.getCapabilities().stream(),
                            flatMapping(cap -> cap.getAttributes().entrySet().stream(),
                                    toMap(Map.Entry::getKey, Map.Entry::getValue)))));
    

    【讨论】:

    • 注意:这是假设在多个 Maps 中不会有重复的键,否则您也可以在同一下游为它们编写自定义合并函数收藏家。
    • 是的,这似乎是要走的路!我正在尝试找出一种方法来通过 Capability 的命名空间属性进行过滤,而不会丢失来自资源对象的引用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 2022-01-21
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    相关资源
    最近更新 更多