Search code examples
javajava-8hashmapjava-streamcollect

How create HashMap from flatMap?


I'm have two Maps in method param.

 private Map<String, List<Attr>> getPropAttr(Map<String, List<Attr>> redundantProperty,
                                                                       Map<String, List<Attr>> notEnoughProperty) {
        Map<String, List<Attr>> propAttr = new HashMap<>();
        redundantProperty.forEach((secondPropertyName, secondPropertyAttributes) -> notEnoughProperty.entrySet().stream()
                .filter(firstPropertyName -> secondPropertyName.contains(firstPropertyName.getKey()))
                .forEach(firstProperty -> {
                    List<Attr> firstPropertyAttrs = firstProperty.getValue();
                    List<Attr> redundantPropAttrs = getRedundantPropAttrs(secondPropertyAttrs, firstPropertyAttrs);

                    String propName = firstProperty.getKey();
                    propAttr.put(propertyName, redundantPropAttrs);
                }));
        return propAttr;

I want to rewrite this method on stream. But, i have some problems in stream collectors. It's don't see return value(List ) from stream into flatmap. In below - my attempt to rewrite this method on stream API. How set second param in collect(toMap(first::get, second::get))? Thank you an advance.

private Map<String, List<Attr>> getPropAttr(Map<String, List<Attr>> redundantProperty,
                                                                       Map<String, List<Attr>> notEnoughProperty) {
    return redundantProperty.entrySet().stream()
            .flatMap(secondProperty -> notEnoughProperty.entrySet().stream()
                    .filter(firstPropertyName -> secondProperty.getKey().contains(firstPropertyName.getKey()))
                    .map(firstProperty -> {
                        List<Attr> onlinePropertyAttrs = firstProperty.getValue();
                        List<Attr> redundantPropAttrs = 
                                getRedundantPropAttrs(secondProperty.getValue(), firstPropertyAttrs);
                        return redundantPropertyAttrs;
                    }))
            .collect(toMap(Property::getName, toList()));

Solution

  • After your flatMap call, your Stream becomes a Stream<List<Attr>>. It looks like you lose the property you want to use as a key for the output Map at this point.

    Instead, I suggest that the map inside the flatMap return a Map.Entry containing the required key and value:

    return redundantProperty.entrySet()
                           .stream()
                           .flatMap(secondProperty ->
                               notEnoughProperty.entrySet()
                                                .stream()
                                                .filter(firstPropertyName -> secondProperty.getKey().contains(firstPropertyName.getKey()))
                                                .map(firstProperty -> {
                                                    List<Attr> redundantPropAttrs = ...
                                                    ...
                                                    return new SimpleEntry<String,List<Attr>>(firstProperty.getKey(),redundantPropertyAttrs);
                                                }))
                           .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));