【问题标题】:How to create a List<Object> with fields String and Map<String, Set<String>> from another List<Object2>如何使用来自另一个 List<Object2> 的字段 String 和 Map<String, Set<String>> 创建 List<Object>
【发布时间】:2021-07-28 05:17:46
【问题描述】:

Object2 类具有标准 getter,并具有 String 字段 folderfileversion。 它被命名为SourceInfo

List&lt;SourceInfo&gt; source 包含上述三个字段。

我的目标是从List&lt;SourceInfo&gt; 创建一个List&lt;Info&gt;

List的类是Info,如下图。


    public class Info {
      private final String folder;
      private final Map<String, Set<String>> file;
    
      public static Builder builder() {
        return new Builder();
      }
    
      public static Builder builder(Info info) {
        return new Builder(info);
      }
    
      private Info(Builder builder) {
        this.folder = builder.folder;
        this.file = builder.file;
      }
    
      public String getFolder() {
        return folder;
      }
    
      public Map<String, Set<String>> getFile() {
        return file;
      }
    
      // autogenerated toString, hashCode, and equals
    
      public static class Builder {
        private String folder;
        private Map<String, Set<String>> file;
    
        private Builder() {}
    
        private Builder(Info info) {
          this.folder = info.folder;
          this.file = info.file;
        }
    
        public Builder with(Consumer<Builder> consumer) {
          consumer.accept(this);
          return this;
        }
    
        public Builder withFolder(String folder) {
          this.folder = folder;
          return this;
        }
    
        public Builder withFile(Map<String, Set<String>> file) {
          this.file = file;
          return this;
        }
    
        public Info build() {
          return new Info(this);
        }
      }

到目前为止,我尝试的是在构建器模式中创建一个集合。


    List<SourceInfo> source;
    
    // error: gc overhead limit exceeded 

    List<Info> infoList = source.stream()
            .map(e -> Info.builder()
                .withFolder(e.getFolder())
                .withFile(source.stream()
                    .collect(Collectors.groupingBy(SourceInfo::getKey,
                        Collectors.mapping(SourceInfo::getVersion, Collectors.toSet()))))
                .build())
            .collect(Collectors.toList());
    
    
    Map<String, Set<String>> map = source.stream()
        .collect(Collectors
            .groupingBy(SourceInfo::getKey,
                Collectors.mapping(SourceInfo::getVersion, Collectors.toSet())));
    
    List<Info> info = source.stream()
        .map(e -> Info.builder()
            .withFolder(e.getFolder())
            .withFile(map.entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey,
                    Map.Entry::getValue)))
            .build())
        .collect(Collectors.toList());


所需的输出。以下语法可能已关闭。

// [String, Map<String, Set<String>>]

Info [folder, [key=file [value=version]]]
...

我是 Java 新手,不胜感激。

我想了解如何使用 java8 和 for 循环来做到这一点。

谢谢。

【问题讨论】:

    标签: java list for-loop set java-stream


    【解决方案1】:

    首先收集到Map&lt;String, Map&lt;String, Set&lt;String&gt;&gt;,然后使用Collectors#collectingAndThenCollectors#groupingBy 将其映射到List&lt;Info&gt;

    List<Info> result = list.stream()
            .collect(Collectors.collectingAndThen(
                    Collectors.groupingBy(
                            Object2::getFolder,
                            Collectors.groupingBy(
                                    Object2::getFile,
                                    Collectors.mapping(
                                            Object2::getVersion,
                                            Collectors.toSet()
                                    )
                            )
                    ),
                    map -> map.entrySet()
                            .stream()
                            .map(entry -> new Info.Builder()
                                                  .withFolder(entry.getKey())
                                                  .withFile(entry.getValue())
                                                  .build()
                            )
                            .collect(Collectors.toList())
            ));
    

    【讨论】:

    • 这不会创建带有String folderMap&lt;String, Set&lt;String&gt;&gt; fileInfo 对象,Collectors#collectingAndThen 的 andThen 强制创建一个新的构造函数来运行,它返回 null对于folderfile。寻找一种无需新字段即可构建 Info 的方法。
    • 不幸的是,信息无法编译,您能先解决这个问题吗?那我去看看。
    • 是的,现在应该可以编译了。谢谢
    • @zzzw3137 我修改了:) 你能检查一下是否正常吗?
    猜你喜欢
    • 1970-01-01
    • 2018-09-22
    • 2020-01-26
    • 2020-08-01
    • 2022-08-19
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多