我想知道我是否可以通过多个键进行分组。 让我说我上了一堂课:
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;
现在的问题是,我应该如何通过使用Collections来实现我想要的行为,比如说这些东西是在名为somethings的List中,所以我可以做类似的事情
somethings.stream().collect(Collectors.groupby(???))
注意我也希望能够改变???通过策略应用不同的分组,将来很容易说,我可能希望将来按名称或ID进行分组。
答案 0 :(得分:0)
解决此问题的一种方法是创建一个方法,确定Function<? super Something, ? extends String>
作为分类器传递给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()));
答案 1 :(得分:0)
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();
}