2

I have a map that contains date as key and (another map of string as key and list as the value) as value. Map<LocalDate, Map<String, List<FlexiServer>>>, I want to populate another map that has String as a key and double as a value. The contents of FlexiServer are

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

So, basically I want to iterate from first the exterior map to get the internal map and then iterate the internal map to get the list of FlexiServers and populate the new map having server number as key and list of quantities as values. How can I do this using java 8 streams?

I tried with for loop, but I will like to replace it using Java streams.

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());
                    }
                }
            }
        }
2
  • 1
    So, what have you tried so far? Commented Mar 5, 2020 at 16:23
  • I tried to do it using for loops but then it was 3 loops nested so I did not find it to be a good approach. Commented Mar 5, 2020 at 16:28

2 Answers 2

3

Just get the values from the outer map and inner map and then use 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())));
Sign up to request clarification or add additional context in comments.

3 Comments

I get an error saying collect (java.util.stream.Collector<? super java.util.List<x.y.z.FlexiServer>,A,R>) in Stream cannot be applied to (java.util.stream.Collector<x.y.z.FlexiServer,capture<?>,java.util.Map<java.lang.String,java.util.List<java.lang.Double>>>) reason: no instance(s) of type variable(s) exist so that List<FlexiServer> conforms to FlexiServer
Thanks, it worked, do you know some good tutorial or post from where I can get my concepts clear about java streams, I know there are many over the internet, but just asking for some recommendations.
This is the best have read in online baeldung.com/java-groupingby-collector @Loui
1

You can do it this way using 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));

2 Comments

Don't try this at home.
What do you mean ?!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.