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
我的 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