如何通过流在HashMap中进行分组

发布于 2025-01-11 20:28:22 字数 1677 浏览 4 评论 0原文

我有以下 DTO 和投影接口:

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

    // constructors
}

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

public interface ProductDTO {
    UUID getProductUuid();

    UUID getProductCategoryUuid();

    boolean getDisabled();
}

但是,当我尝试通过分组 getProductCategoryUuid 及其相应的 List 来创建映射时,我在 new StatusDTO(...) 部分中收到错误 “UUID 不是函数式接口”“boolean 不是函数式接口”界面”

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

我是否需要像我下​​面尝试的那样 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())));

I have the following DTO and projection interface:

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

    // constructors
}

I fill these fields in my repository:

public interface ProductDTO {
    UUID getProductUuid();

    UUID getProductCategoryUuid();

    boolean getDisabled();
}

However, when I try to create a mapping by grouping getProductCategoryUuid and its corresponding List<StatusDTO>, I get error in the new StatusDTO(...) part as "UUID is not a functional interface" and "boolean is not a functional interface".

So, how can I build a map using ProductDTO::getProductCategoryUuid - List<StatusDTO> pairs?

Do I need LinkedHashMap as I tried below?

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()));

Update: The foolowing approach seems to work, but I am not sure if it is a proper way. I use LinkedHashMap to maintain order. Any idea?

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())));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

累赘 2025-01-18 20:28:23

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

Lambda 表达式方法引用 应符合 <强>功能性界面。

这是一个接口,包含一个且仅有一个抽象方法(并且注意:此方法的签名不得与其中一种方法匹配在 Object 类中定义)。

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

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

ProductDTO 必须是函数接口。由于 ProductDTO 是一个,所以你不能这样做。

仅当需要函数时才可以使用方法引用。由于此构造函数不需要函数,即使将其放置在收集器中,也不意味着现在将 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

我需要像下面尝试的那样使用 LinkedHashMap 吗?

如果您添加只是为了尝试使代码编译,那么答案是。仅当您需要维护条目添加顺序时才使用 LinkedHashMap。默认情况下 groupingBy() 为您提供的 HashMap 应始终优先于 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())

Seems like you are getting the concept of method references wrong. Not every method call can be replaced by a method reference.

Lambda expressions and method references should conform to a functional interface.

Which is an interface that contains one and only one abstract method (and note: the signature of this method must not match to one of the methods defined in the Object class).

Hence, in order to be able to use method references in the constructor call

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

type ProductDTO must be a functional interface. And since ProductDTO is a class you can't do that.

You can use method references only when function is expected. Since this constructor doesn't expect functions, even if you place it inside a collector, it doesn't mean that now it's illegible to pass lambdas to it.

Another mistake is that Collectors.toList() must be a downstream collector of Collectors.mapping() but not Collectors.groupingBy(). So the overall structure of your collector will be the following:

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?

If you added only in order to try to make the code compile, the answer is no. Use LinkedHashMap only if you need to maintain the order in which entries were added. HashMap which groupingBy() will give you by default should be always preferred over LinkedHashMap. If you don't need it, then just remove the mapFactory from your collector.

Assuming that LinkedHashMap is required for your purposes, the collector will look like this:

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())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文