如何通过流在 HashMap 中分组

How to group in HashMap via stream

我有以下DTO和投影接口:

@Data
public class StatusDTO{
    private UUID productUuid;
    private boolean disabled;

    // constructors
}

我在我的存储库中填写这些字段:

public interface ProductDTO {
    UUID getProductUuid();

    UUID getProductCategoryUuid();

    boolean getDisabled();
}

但是,当我尝试通过分组 getProductCategoryUuid 及其对应的 List<StatusDTO> 来创建映射时,我在 new StatusDTO(...) 部分出现错误,因为 "UUID 是不是功能接口""boolean 不是功能接口".

那么,如何使用 ProductDTO::getProductCategoryUuid - List<StatusDTO> 对构建地图?

我需要 LinkedHashMap 吗?

final Map<UUID, List<StatusDTO>> map = demoService.findAll().stream()
        .collect(groupingBy(ProductDTO::getProductCategoryUuid, LinkedHashMap::new,
                Collectors.mapping(new StatusDTO(
                                           ProductDTO::getProductUuid, 
                                           ProductDTO::getDisabled)
                                  ), Collectors.toList()));

更新: 愚蠢的方法似乎有效,但我不确定它是否是正确的方法。我使用 LinkedHashMap 来维持秩序。有什么想法吗?

final Map<UUID, List<StatusDTO>> map = demoService.findAll().stream()
                .collect(groupingBy(
                             ProductDTO::getProductCategoryUuid, LinkedHashMap::new,
                             Collectors.mapping(p -> new StatusDTO(
                                 p.getProductUuid(), 
                                 p.getDisabled()), 
                 Collectors.toList())));

您似乎对 方法引用 的概念理解有误。并非每个方法调用都可以用方法引用代替。

Lambda expressions and method references 应该符合 功能接口 .

这是一个接口,它包含一个且只有一个抽象方法(并且注意: 此方法的签名不得与 Object class).

中定义的方法之一匹配

因此,为了能够在构造函数调用中使用方法引用

new StatusDTO(ProductDTO::getProductUuid, ProductDTO::getDisabled)

类型 ProductDTO 必须是 功能接口 。因为 ProductDTOclass 你不能那样做。

您只能在需要函数时使用方法引用。由于此构造函数不期望函数,即使您将它放在收集器中,也不意味着现在将 lambda 传递给它会变得难以辨认。

另一个错误是 Collectors.toList() 必须是 Collectors.mapping() 的下游收集器,但 不是 Collectors.groupingBy()。所以你的收集器的整体结构如下:

Collectors.groupingBy(function that extracts a KEY,
                      mapFactory, // <- resulting map (optional argument)
                      Collectors.mapping(function that transforms a VALUE, 
                                         Collectors.toList()) // <- downstream collector that defenses how VALUES will be represented in the resulting map

Do I need LinkedHashMap as I tried below?

如果你添加只是为了让代码编译通过,答案是。仅当您需要维护添加条目的顺序时才使用 LinkedHashMapHashMap 默认情况下 groupingBy() 应该比 LinkedHashMap 更受青睐。如果您不需要它,只需从您的收集器中删除 mapFactory

假设您的目的需要 LinkedHashMap,收集器将如下所示:

Collectors.groupingBy(ProductDTO::getProductCategoryUuid,
                LinkedHashMap::new, // <- remove this argument if there's no such requirement 
                Collectors.mapping(product -> new StatusDTO(product.getProductUuid(),
                                                            product.getDisabled()),
                                   Collectors.toList())