And*_*sky 13 java java-8 java-stream
有两个类和两个相应的列表:
class Click {
long campaignId;
Date date;
}
class Campaign {
long campaignId;
Date start;
Date end;
String type;
}
List<Click> clicks = ..;
List<Campaign> campaigns = ..;
Run Code Online (Sandbox Code Playgroud)
并希望找到所有Click的clicks:
列表中有相应Campaign的campaigns,即Campaign具有相同的campaignIdAND
这Campaign有type="预期"和
这Campaigns.start< click.date<Campaigns.end
到目前为止,我有以下实现(这对我来说似乎令人困惑和复杂):
clicks.
stream().
filter(click -> campaigns.stream().anyMatch(
campaign -> campaign.getCampaignType().equals("prospecting") &&
campaign.getCampaignId().equals(click.getCampaignId()) &&
campaign.getStart().after(click.getDate()) &&
campaign.getEnd().before(click.getDate()))).
collect(toList());
Run Code Online (Sandbox Code Playgroud)
我想知道这个问题是否有更简单的解决方案.
突出的一件事是您的第二个要求与匹配无关,它只是一个条件campaigns。您必须测试这是否对您更好:
clicks.stream()
.filter(click -> campaigns.stream()
.filter(camp -> "prospecting".equals(camp.type))
.anyMatch(camp ->
camp.campaignId == click.campaignId &&
camp.end.after(click.date) &&
camp.start.before(click.date)
)
)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
否则,我从未见过不涉及在第一个谓词中流式传输第二个集合的流解决方案,因此您不能做得比您所做的更好。在可读性方面,如果它看起来让您感到困惑,那么创建一个测试布尔条件的方法并调用它:
clicks.stream()
.filter(click -> campaigns.stream()
.filter(camp -> "pre".equals(camp.type))
.anyMatch(camp -> accept(camp, click))
)
.collect(Collectors.toList());
static boolean accept(Campaign camp, Click click) {
return camp.campaignId == click.campaignId &&
camp.end.after(click.date) &&
camp.start.before(click.date);
}
Run Code Online (Sandbox Code Playgroud)
最后,2个不相关的建议:
Date类,而是使用新的java.time API的LocalDate。Campaign'stype只能有一些预定义的值(如“提交”、“展望”、“接受”...),那么 anenum将比一般 更适合String。嗯,有一种非常巧妙的方法可以解决您的问题 IMO,来自 Holger 的原始想法(我会找到问题并在此处链接)。
您可以定义执行检查的方法(我已经简化了一点):
static boolean checkClick(List<Campaign> campaigns, Click click) {
return campaigns.stream().anyMatch(camp -> camp.getCampaignId()
== click.getCampaignId());
}
Run Code Online (Sandbox Code Playgroud)
并定义一个绑定参数的函数:
public static <T, U> Predicate<U> bind(BiFunction<T, U, Boolean> f, T t) {
return u -> f.apply(t, u);
}
Run Code Online (Sandbox Code Playgroud)
用法是:
BiFunction<List<Campaign>, Click, Boolean> biFunction = YourClass::checkClick;
Predicate<Click> predicate = bind(biFunction, campaigns);
clicks.stream()
.filter(predicate::test)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
31244 次 |
| 最近记录: |