'Java stream: Grouping HashMap key values to prevent duplicate keys

I have the following HashMap in my Java app:

final Map<UUID, Boolean> map = demoRepo.demoService.stream()
        .collect(Collectors.toMap(
                ProductDTO::getMenuUuid,
                ProductDTO::getStatus));

However, as the result contains multiple menuUuid value, I need to group them as the key does not contain the same value. So, how should I do this using stream?

Update: I also tried groupingBy as shown below, but I think the usage is not correct:

final Map<UUID, Boolean> map = sdemoRepo.demoService.stream()
                .collect(Collectors.groupingBy(
                        ProductDTO::getMenuUuid, LinkedHashMap::new,
                        Collectors.mapping(ProductDTO::getStatus)));

Suppose that I have the following stream:

MenuUuid   |   Status |
-----------------------
1              true
2              false
1              true
1              true
3              true
2              false

Then I need a map result like; 1:true, 2:false, 3:true



Solution 1:[1]

The Collectors.toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction) allows the caller to define a BinaryOperator mergeFunction that returns the correct value if the stream provides a key-value pair for a key that already exists.

The following example uses the Boolean.logicalOr method to combine the existing value with the new one. Equal UUID keys are not grouped,since the result is a single key-single value map. But

final Map<UUID, Boolean> map = demoRepo.demoService.stream()
        .collect(Collectors.toMap(
                ProductDTO::getMenuUuid,
                ProductDTO::getStatus,
                 Boolean::logicalOr));

In particular Boolean::logicalOr is a function that is called if the map already contains a value for the key. In this case, the Boolean::logicalOr takes as argument the existing map value and the new value from the Stream` and returns the Logical Or of these two, as the result. This results is then entered in the map.

Solution 2:[2]

You will have to merge the values. See if it helps

final Map<UUID, Boolean> map  =
    demoRepo.stream().filter(Objects::nonNull)
        .collect(
            Collectors.toMap(
                ProductDTO::getMenuUuid,
                ProductDTO::getStatus,
                (menuUuid, status) -> {
                  menuUuid.addAll(status);
                  return menuUuid;
                }));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Alagu Narayanan K