提问人:turing23 提问时间:11/4/2023 最后编辑:user207421turing23 更新时间:11/6/2023 访问量:94
使用 Java8 Streams 减少 if-else 语句,同时过滤多个条件
Reduce if-else statements with Java8 Streams while filtering multiple conditions
问:
我从同行那里得到了评论,说我需要减少在代码中使用多个 If-else 块,而是使用命令式编程技术来实现相同的功能
背景我有一个事件列表,我需要根据几个条件返回一个事件对象。对于 SOP 事件和 SOP 确认事件,列表的大小可以是 2 或 3,对于非 SOP 确认事件,大小为 2,但事件类型不同,最后是大小为 1 的单个事件。
//All Required Predicates
//SOP Special Event
if(eventList.size() >1 && results.getAcknowledgeUid().isEmpty()){
event = eventList.stream().filter(isOriginalEvent.and(isSOPEvent).and(isSOPSpecialEvent))
.findFirst().orElse(null);
}
else if (eventList.size() >1 && !results.getAcknowledgeUid().isEmpty()) {
// SOP Acnknowledge Event
if("SOP".equalsIgnoreCase(eventList.get(0).getEventType())) {
event = eventList.stream().filter(isAcknowledgeEvent)
.findFirst().orElse(null);
}
// Non SOP Acnknowledge Event
List<event> eventAcnknowledgeList = repository.findEventByUid(results.getAcnknowledgeUid);
event = eventAcnknowledgeList.stream().filter(isAcnknowledgeEvent)
.findFirst().orElse(null);
}
// Single Event
else if (eventList.size() >0) {
event = eventList.stream().filter(isOriginalEvent).findFirst().orElse(null);
}
我将 if else 块中的所有条件都移动到谓词中,它现在看起来很紧凑。但我仍然无法减少 if-else 链。我考虑过使用三元运算符来合并第二个和第三个块,但如果我这样做,代码看起来很笨拙。 我也无法执行以下操作。
Predicate<List<Event>> isMoreThanTwoEvents = event -> eventList.size() > 1;
event = eventList.stream().filter(isAcknowledgeEvent.and(isSOPEvent).and(isMoreThanTwoEvents))
.findFirst().orElse(null);
这让我在IDE中出现错误
必需类型谓词<?超级活动> 提供的谓词<列表>
- 如何减少 If-Else 链接?
- 如何筛选集合中流中超出该集合范围的数据?
- 这个问题有没有更好或更优雅的解决方案?
答:
0赞
GreyBeardedGeek
11/5/2023
#1
一种简单的方法是使用提前回报。
例如
if(foo) {
return "foo";
}
if(bar) {
return "bar";
}
etc...
2赞
Bohemian
11/6/2023
#2
流和谓词不是灵丹妙药,普通 s 也没有错。if
小规模的重构,主要是删除冗余条件,产生:
if (eventList.size() > 1) { //SOP Special Event
if (results.getAcknowledgeUid().isEmpty()) {
event = eventList.stream().filter(isOriginalEvent.and(isSOPEvent).and(isSOPSpecialEvent))
.findFirst().orElse(null);
} else {
if ("SOP".equalsIgnoreCase(eventList.get(0).getEventType())) { // SOP Acnknowledge Event
event = eventList.stream().filter(isAcknowledgeEvent)
.findFirst().orElse(null);
} else { // Non SOP Acnknowledge Event
event = eventAcnknowledgeList = repository.findEventByUid(results.getAcnknowledgeUid)
.stream().filter(isAcnknowledgeEvent)
.findFirst().orElse(null);
}
} else { // Single Event
event = eventList.stream().filter(isOriginalEvent).findFirst().orElse(null);
}
具有良好的可读性。
1赞
Jean-Baptiste Yunès
11/6/2023
#3
至少那个块是错误的:
// SOP Acnknowledge Event
if("SOP".equalsIgnoreCase(eventList.get(0).getEventType())) {
event = eventList.stream().filter(isAcknowledgeEvent)
.findFirst().orElse(null);
}
// Non SOP Acnknowledge Event
List<event> eventAcnknowledgeList = repository.findEventByUid(results.getAcnknowledgeUid);
event = eventAcnknowledgeList.stream().filter(isAcnknowledgeEvent)
.findFirst().orElse(null);
还有一个(可能)缺少其他东西,不是吗?
// SOP Acnknowledge Event
if ("SOP".equalsIgnoreCase(eventList.get(0).getEventType())) {
event = eventList.stream().filter(isAcknowledgeEvent)
.findFirst().orElse(null);
} else {
// Non SOP Acnknowledge Event
List<event> eventAcnknowledgeList = repository.findEventByUid(results.getAcnknowledgeUid);
event = eventAcnknowledgeList.stream().filter(isAcnknowledgeEvent)
.findFirst().orElse(null);
}
如果是;
if (n>1 && cond)
else if (n>1 && !cond)
else if (n>0)
至少测试两次是多余的。你可以这样写:cond
if (n>1)
if (cond)
else
else if (n>0)
如果始终为 1、2 或 3,则可能会删除最后一个测试:n
if (n>1)
if (cond)
else
else
这给了:
if (eventList.size()>1) {
if (results.getAcknowledgeUid().isEmpty()) {
event = eventList.stream().filter(isOriginalEvent.and(isSOPEvent).and(isSOPSpecialEvent))
.findFirst().orElse(null);
} else {
// SOP Acnknowledge Event
if("SOP".equalsIgnoreCase(eventList.get(0).getEventType())) {
event = eventList.stream().filter(isAcknowledgeEvent)
.findFirst().orElse(null);
} else {
// Non SOP Acnknowledge Event
List<event> eventAcnknowledgeList = repository.findEventByUid(results.getAcnknowledgeUid);
event = eventAcnknowledgeList.stream().filter(isAcnknowledgeEvent)
.findFirst().orElse(null);
}
else {
event = eventList.stream().filter(isOriginalEvent).findFirst().orElse(null);
}
您还可以分解对 findFirst.orElse 和过滤器的调用:
Stream<SOMETYPE> s = null;
Predicate<SOMETYPE> f = null
if (eventList.size()>1) {
if (results.getAcknowledgeUid().isEmpty()) {
s = eventList.stream();
f = isOriginalEvent.and(isSOPEvent).and(isSOPSpecialEvent);
} else {
if("SOP".equalsIgnoreCase(eventList.get(0).getEventType())) {
s = eventList.stream()
} else {
s = repository.findEventByUid(results.getAcnknowledgeUid).stream()
}
f = filter(isAcnknowledgeEvent);
else {
s = eventList.stream();
f = isOriginalEvent;
}
event = s.filter(f).findFirst().orElse(null);
评论
0赞
turing23
11/7/2023
非常感谢你@JeanBaptiste 即使我正在嵌套 if else 块,我也希望我的评论能通过,因为这非常简洁明了。这也将帮助我将来更好地设计我的代码。
评论