使用流从内部对象分组Map属性?

Cri*_*ano 8 java collections java-8 java-stream java-11

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

class Resource {
   List<Capability> capabilities;
}

class Capability {
   String namespace;
   Map<String, Object> attributes;
}
Run Code Online (Sandbox Code Playgroud)

我有一个资源流,我想从两个不同的命名空间("a","b")中提取所有的功能属性到Map<Resource, Map<String, Object>>我确信没有重复键.

我做了很多尝试使用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()))));
Run Code Online (Sandbox Code Playgroud)

似乎我走在了正确的道路上.

Nik*_*las 6

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

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
Run Code Online (Sandbox Code Playgroud)

我们假设样本输入是:

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}]]]
Run Code Online (Sandbox Code Playgroud)

然后上面的代码将导致:

a: [aa1, aa3, aa2]
b: [bb1, bb3, bb2]
c: [cc1, cc3, cc2]
Run Code Online (Sandbox Code Playgroud)


Nam*_*man 5

你也可以使用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)))));
Run Code Online (Sandbox Code Playgroud)

  • *注意*:这假设在多个`Map`s中没有重复键,否则你也可以在同一个下游收集器中为它们编写自定义合并函数. (3认同)