Java 流:对 HashMap 键值进行分组以防止重复键

Java stream: Grouping HashMap key values to prevent duplicate keys

我的 Java 应用程序中有以下 HashMap:

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

但是,由于结果包含多个 menuUuid 值,我需要将它们分组,因为键不包含相同的值。那么,我应该如何使用流来做到这一点?

更新:我也试过groupingBy如下图,但我觉得用法不正确:

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

假设我有以下流:

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

然后我需要一个地图结果,例如; 1:true、2:false、3:true

Collectors.toMap(函数keyMapper, 函数值映射器, BinaryOperator mergeFunction) 允许调用者定义 BinaryOperator mergeFunction,如果流为已存在的键提供 key-value 对,则 returns 正确的值。

以下示例使用 Boolean.logicalOr 方法将现有值与新值组合。 不对相同的 UUID 键进行分组,因为结果是单个 key-single 值映射。但是

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

特别是 Boolean::logicalOr 是一个函数,如果映射已经包含键的值,则会调用该函数。在这种情况下,Boolean::logicalOr takes as argument the existing map value and the new value from the Stream` 和 returns 这两个的逻辑或作为结果。然后将此结果输入到地图中。

您必须合并这些值。看看有没有帮助

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

如果所有用户 ID 都具有相同的布尔值,则只需执行以下操作:

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

最后一个lambda,是一个合并函数。它用于决定如何合并重复键。在这种情况下,它只保留已经存在的第一个。您也可以使用新的,因为您并没有真正改变 boolean 并且它们都是相同的值。

如果您的 ProductDTO class 使用 UUID 通过 equals() 确定相等性,您还可以执行以下操作:

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

这是可行的,因为您不会有任何重复的 UUID