Search code examples
javajava-8java-stream

Simplify a list where every element is itself a list of maps using Java streams


After parsing my JSON file with JSON Parser, I get the following list in Java:

List<List<HashMap<String,String>>> fields  = jsonContext.read(jsonPath);

Every element in this list is itself a list of HashMaps and results from the following JSON structure:

[
  {
   "value": "such",
   "name": "yname"
  },
  {
    "value": "Suchwort",
    "name": "yvbeds"
  },
  {
    "value": "",
    "name": "yfix"
  },
  {
    "value": "such",
    "name": "yzielfeld"
   }
],
[
  {
   "value": "ftext",
   "name": "yname"
  },
  {
   "value": "Freitext 1",
   "name": "yvbeds"
  },
  {
    "value": "",
    "name": "yfix"
  },
  {
    "value": "ftext",
    "name": "yzielfeld"
  }
],

This JSON structure creates four maps, each having two key/value pairs. I would like to convert these four maps into a single map. I have achieved this without using streams as follows:

List<HashMap<String,String>> newList = new ArrayList<>();

for(int i=0;i< fields.size();i++) {
    HashMap<String,String> singleMap = new HashMap<>();
    List<HashMap<String,String>> listItem = fields.get(i);
    for(int j=0;j<listItem.size();j++) {
        HashMap<String,String> fieldMap = listItem.get(j);
        singleMap.put(fieldMap.get("name"),fieldMap.get("value"));
    }
    newList.add(singleMap);

}

I have tried the following stream approach but after collecting to map, I need to collect to List again but there are only map options:

List<HashMap<String,String>> newList = fields.stream()
   .flatMap(List::stream)
   .collect(Collectors.toMap(value->value.get("name"),value->value.get("value")))
   .

How can I implement this using streams?


Solution

  • From your non-stream code, you seem to want to map each inner list into its own separate Map.

    Therefore, you should not flatten (flatMap) the outer list. map the outer list, and collect(toMap) each inner list.

    List<Map<String, String>> result = fields.stream()
        .map(
            l -> l.stream().collect(
                // assuming the maps in each inner list do not have duplicate names
                Collectors.toMap(x -> x.get("name"), x -> x.get("value"))
                // if they do, give an appropriate merger function as the 3rd argument
            )
        )
        .toList();