【问题标题】:Java Customized GroupingBy with || ConditionJava 自定义 GroupingBy 与 ||健康)状况
【发布时间】:2017-09-30 09:30:11
【问题描述】:

我想看看我是否可以按多个键进行分组。 假设我有一门课:

Class Something {
    String name;
    String id;
}

还有一个清单:

  Name     id

  David    123
  David    456
  Bryant   123
  Ryan     456
  Foo      555
  Bar      555

我可以将它们分组

[(David, 123), (David, 456), (Bryant, 123), (Ryan, 456)]
[(Foo, 555), (Bar, 555)]

这意味着,我希望类“等于”的行为是名称或 id 相同,类等于,这样

public boolean equals(Object o) {
    Something that = (Something) o;
    return this.name.equals(that.name) || this.id.equals(that.id);
}

但是那个equals函数的问题是不可传递的,这意味着我不能为它写一个对应的hashCode函数。

我知道如果我写两个哈希图,我可以通过这样做来实现这一点

Map<String, Something> idToSomething;
Map<String, Something> nameToSomething;

现在的问题是,我应该如何通过使用集合来实现我想要的行为,比如这些东西是否在一个名为 somethings 的列表中,所以我可以做类似的事情

somethings.stream().collect(Collectors.groupby(???))

请注意,我也希望能够更改 ???将来通过按策略应用不同的分组很容易,比如说我将来可能只想按名称或 id 分组。

【问题讨论】:

  • 你可能想看看 Google Guava 的 Multimap

标签: java java-8 java-stream collectors


【解决方案1】:

解决此问题的一种方法是创建一个方法来确定 Function&lt;? super Something, ? extends String&gt; 用作传递给 Collectors#groupingBy 的分类器,并使用全局变量来确定应该使用哪个:

private boolean shouldIdBeUsed = true;

public Function<? super Something, ? extends String> getClassifier() {
    if (shouldIdBeUsed) {
        return Something::getId;
    }

    return Something::getName;
}

现在,您可以简单地将方法作为参数传递:

somethings.stream().collect(Collectors.groupingBy(getClassifier()));

【讨论】:

  • hmm... 但它总是要使用的 id 或要使用的名称。该布尔值需要同时为真和假?
  • 我不确定你在问什么,但我提供了一个例子。您可以删除布尔值并添加您想要的任何其他条件。
【解决方案2】:

Jacob 的一些扩展回答。

        Map<UUID, List<BookingOutput.CostsQuoteSummary>> quotesPerUsers = bookings.stream()
            .map(booking -> new BookingOutput.CostsQuoteSummary(
                    booking,
                    timesheet.getDates().getFrom(),
                    timesheet.getDates().getTo()
            ))
            .collect(Collectors.groupingBy(groupCostsPerUser(uuidGenerator)));

我们添加groupCostsPerUser(uuidGenerator) 方法,封装我们需要的任何条件。以我为例:

private Function<BookingOutput.CostsQuoteSummary, UUID> groupCostsPerUser(UUIDGenerator uuidGenerator) {
    return costsQuoteSummary -> costsQuoteSummary.hasUserId() ? costsQuoteSummary.getUserId()
            : uuidGenerator.generateV4(); 
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 2013-04-24
    • 2022-06-27
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多