简体   繁体   中英

How to merge List<String> during groupingBy

How to merge List<String> during groupingBy ?

Given a list of custom object EligibilityRequest where there are some duplicates, I'd need to group those instances of EligibilityRequest which are equal and then merge into list of String a specific property which is not contributing to the Equals method.

Here is the details:

public class EligibilityRequest {

 private String channel; // it's part of Equals
 ...

 private List<String> productCodes // it's not part of Equals and need to be aggregated within instance of EligibilityRequest "equal"

}

I tried the following:

  Map<EligibilityRequest, List<String>> uniqueEligibilityRequests = new HashMap<>();

  uniqueEligibilityRequests = requests.stream()
            .collect(groupingBy(request -> request,
                    Collectors.mapping(request -> request.getProductsCode(), toList())
                    ));

It works as long as the productCodes represents a String instead of List<String> . I'm not able to figure it out how to merge different List<String> instead within the groupingBy .

Can someone help there?

Regards, Vincenzo

The code you have is appropriate for creating a map where values are lists of lists:

Map<EligibilityRequest, List<List<String>>> result = 
      requests.stream()
              .collect(groupingBy(request -> request,
                    Collectors.mapping(request -> request.getProductsCode(), 
                                       toList())
                ));

If your intent is to collect all those inner lists into a single one, then you need this to flatten inner lists:

Map<EligibilityRequest, List<String>> res = 
        requests.stream()
        .collect(Collectors.groupingBy(Function.identity(),
                 Collectors.mapping(
                        EligibilityRequest::getProductCodes,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> list.stream()
                                            .flatMap(List::stream)
                                            .collect(Collectors.toList())))
                        )
                );

In this given situation, I find no-stream code is more comfortable.

public static <K extends Comparable<K>> Map<K, Set<String>> groupBy(List<EligibilityRequest> requests, Function<EligibilityRequest, K> getKey) {
    Map<K, Set<String>> map = new TreeMap<>();

    for (EligibilityRequest request : requests) {
        map.compute(getKey.apply(request), (key, productCodes) -> {
            productCodes = productCodes == null ? new TreeSet<>() : productCodes;
            productCodes.addAll(request.getProductCodes());
            return productCodes;
        });
    }

    return map;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM