【问题标题】:Iterating a list inside a map of map using java 8 streams使用java 8流在地图地图内迭代列表
【发布时间】:2020-03-05 16:01:56
【问题描述】:

我有一个包含日期作为键的映射和(另一个字符串映射作为键和列表作为值)作为值。 Map<LocalDate, Map<String, List<FlexiServer>>>,我想填充另一个以 String 为键并以 double 为值的映射。 FlexiServer的内容是

public class FlexiServer {
    private String serverNumber;
    private Double quantity;
    private Integer level;
    private String parentServer;
}

所以,基本上我想从首先迭代外部地图以获取内部地图,然后迭代内部地图以获取 FlexiServer 列表并填充具有服务器编号作为键和数量列表作为值的新地图。如何使用 java 8 流来做到这一点?

我尝试使用 for 循环,但我想使用 Java 流替换它。

if(data.isPresent()) {
            for(Map.Entry<LocalDate, Map<String, List<FlexiServer>>> entry : data.get().entrySet()) {
                for(Map.Entry<String, List<FlexiServer>> innerEntry : entry.getValue().entrySet()) {
                    for(FlexiServer dto : innerEntry.getValue()) {
                        dailyRequirements.computeIfAbsent(dto.getserverNumber(),
                            k -> new ArrayList<>()).add(dto.getQuantity());
                    }
                }
            }
        }

【问题讨论】:

  • 那么,到目前为止,您尝试了什么?
  • 我尝试使用 for 循环来实现,但后来嵌套了 3 个循环,所以我发现它不是一个好方法。

标签: java java-8 java-stream


【解决方案1】:

只需从外部映射和内部映射中获取值,然后使用Collectors.groupingby

Map<String, List<Double>> result = map.values()
                                      .stream()
                                      .map(Map::values)
                                      .flatMap(Collection::stream)
                                      .flatMap(List::stream)
            .collect(Collectors.groupingBy(FlexiServer::getServerNumber, Collectors.mapping(FlexiServer::getQuantity, Collectors.toList())));

【讨论】:

  • 我收到一个错误,说不能将 Stream 中的 collect (java.util.stream.Collector super java.util.List,A,R>) 应用于 (java.util .stream.Collector,java.util.Map>>) 原因:没有类型变量的实例(s) 存在使得 List 符合 FlexiServer
  • 谢谢,它成功了,你知道一些好的教程或帖子,我可以从那里清楚地了解 java 流的概念,我知道互联网上有很多,但只是要求一些建议。
  • 这是最好的在线阅读baeldung.com/java-groupingby-collector@Loui
【解决方案2】:

您可以使用 Java8 StreamApi 做到这一点

    Map<LocalDate, Map<String, List<FlexiServer>>> localDateMapMap = new HashMap<>();
    localDateMapMap.put(LocalDate.now(), new HashMap<String, List<FlexiServer>>() {{
      put("1", new ArrayList<FlexiServer>() {{
        add(new FlexiServer() {{
          setQuantity(200D);
          setServerNumber("001");
        }});
        add(new FlexiServer() {{
          setQuantity(500D);
          setServerNumber("001");
        }});
        add(new FlexiServer() {{
          setQuantity(800D);
          setServerNumber("002");
        }});
      }});
      put("2", new ArrayList<FlexiServer>() {{
        add(new FlexiServer() {{
          setQuantity(200D);
          setServerNumber("003");
        }});
        add(new FlexiServer() {{
          setQuantity(500D);
          setServerNumber("001");
        }});
        add(new FlexiServer() {{
          setQuantity(800D);
          setServerNumber("001");
        }});
      }});
    }});
    Map<String, Double> map = new HashMap<>();
    localDateMapMap.values().stream()
        .map(Map::values)
        .flatMap(Collection::stream)
        .flatMap(Collection::stream)
        .forEach(flexiServer -> {
          if (map.containsKey(flexiServer.getServerNumber())) {
            map.replace(flexiServer.getServerNumber(),
                map.get(flexiServer.getServerNumber()) + flexiServer.getQuantity());
          } else {
            map.put(flexiServer.getServerNumber(), flexiServer.getQuantity());
          }
        });
    map.forEach((serverNumber, quantity) -> System.out
        .println("ServerNumber = " + serverNumber + "  Quantity = " + quantity));

【讨论】:

  • 不要在家里尝试这个。
  • 什么意思?!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多