Using streams to extract specific entries of a List of Maps in to a new Map

Solution 1:

Here is a working solution with streams:

Map<String, Object> fields = ((List<Map<String, Object>>) ((Map<String, Object>) document.entrySet()
            .stream()
            .filter(entry -> entry.getKey().equals("cardType"))
            .findFirst()
            .orElseThrow(() -> new RuntimeException("card type not found"))
            .getValue())
            .entrySet()
            .stream()
            .filter(entry -> entry.getKey().equals("cardFields"))
            .findFirst()
            .orElseThrow(() -> new RuntimeException("card fields not found"))
            .getValue())
            .stream()
            .collect(Collectors.toMap(el -> el.get("fieldName").toString(), element -> element.get("fieldLabel")));
Document result = new Document(fields);
System.out.println(result.toJson());

That's probably the worst code i have written - absolutely unreadable and you can't debug it. I would suggest that you do not use stream for this particular task, it isn't the right tool for it. So here is another working solution using Map.get(key):

Map<String, Object> cardType = (Map<String, Object>) document.get("cardType");
List<Map<String, Object>> cardFields = (List<Map<String, Object>>) cardType.get("cardFields");
Document result = new Document();
cardFields.forEach(cardField -> result.put((String) cardField.get("fieldName"), cardField.get("fieldLabel")));
System.out.println(result.toJson());

This is shorter, readable, you can debug it if needed and probably it's more performant. I'd say it's much better overall.

Solution 2:

You may be able to parse your document like this:

Document cardType = document.get("cardType", Document.class);
final Class<? extends List> listOfMaps = new ArrayList<Map<String, String>>().getClass();
List<Map<String, String>> fields = cardType.get("cardFields", listOfMaps);
fields.stream().map(f -> {
    System.out.println(f.get("fieldName") + ": " + f.get("fieldLabel"));
    // here you can construct your new object
}).collect(Collectors.toList());