如何将流用于具有多个条件检查的逻辑?
How to use streams for the logic with multiple conditional checks?
我正在学习 Java 11,并想使用 Java 11 编写以下逻辑块。任何输入都会有所帮助。由于它有很多条件检查,我们可以使用 lambda 或流来实现以下逻辑块。
@Data
class MyDetails{
private String name;
private String status;
private Integer spreadValue;
private Object value;
...
}
public List<MyDetails> returnValidList(Collection<MyDetails> myDetails){
for (MyDetails myDetail : myDetails){
if (myDetail !=null && myDetail.getValue()!=null){
if (myDetail.getSpreadValue()==3 || myDetail.getSpreadValue()==4){
if (myDetail.getName().equalsIgnoreCase("AUTO") || myDetail.getName().equalsIgnoreCase("HOME")){
result.add(myDetail);
} else {
result.add(myDetail);
}
}
}
return result;
}
}
我尝试了以下代码,但列表大小为零,预期列表大小为 17。任何更正以下代码段的建议。
List<MyDetails> result = myDetails.stream()
.filter(Objects::nonNull)
.filter(obj -> Objects.nonNull(obj.getValue()))
.filter(obj -> obj.getSpreadValue() == 3 || obj.getSpreadValue() == 4)
.collect(Collectors.toList());
您唯一可以做的就是通过 Stream API.
链接 filter
调用
List<MyDetails> result = myDetails.stream()
.filter(Objects::nonNull)
.filter(obj -> Objects.nonNull(obj.getValue()))
.filter(obj -> obj.getSpreadValue() == 3 || obj.getSpreadValue() == 4)
.filter(obj -> obj.getName().equalsIgnoreCase("AUTO") || obj.getName().equalsIgnoreCase("HOME"))
.collect(Collectors.toList());
以更复杂的方式,您可能希望将条件提取到单独的变量或方法(返回 Predicate<MyDetails>
)。但是,在高级和可配置过滤的情况下,我建议迭代一个集合可以在应用程序之前先过滤的此类谓词的数量:
// Predicate list
List<Predicate<MyDetails>> predicates = List.of(
Objects::nonNull, // should be always first
obj-> Objects.nonNull(obj.getValue()),
obj-> obj.getSpreadValue() == 3 || obj.getSpreadValue() == 4,
obj-> obj.getName().equalsIgnoreCase("AUTO") || obj.getName().equalsIgnoreCase("HOME")
);
// Reduction using AND. If no predicate is qualified,
// ... a predicate that everything passes through is returned (identity)
Predicate<MyDetails> predicate = predicates.stream()
.reduce(obj -> true, Predicate::and);
// Apply the predicate
List<MyDetails> result = myDetails.stream()
.filter(predicate)
.collect(Collectors.toList());
实现注意事项:
- Stream API 在这种情况下没有任何改进,除非您需要可配置或高级过滤。
- 如果你想有可配置的谓词,使用
LinkedHashMap
并按键过滤不需要的谓词。
还有一些代码审查,只要你的代码看起来很不完整(虽然我尽力格式化它并使其清晰):
- 您的方法中还漏掉了另一个
return
。
private Something value;
在 MyDetails
定义中缺失。
List<MyDetails>
在方法中未定义(记得你调用getValue()
)。
obj.getSpreadValue() == 3 || obj.getSpreadValue() == 4)
和 obj.getName().equalsIgnoreCase("AUTO") || obj.getName().equalsIgnoreCase("HOME")
是重构的对象。我建议使用 HashSet
和 Set::contains
.
AUTO
和 HOME
名称的条件检查无关紧要,因为 both 分支都会导致将项目添加到列表中。
我正在学习 Java 11,并想使用 Java 11 编写以下逻辑块。任何输入都会有所帮助。由于它有很多条件检查,我们可以使用 lambda 或流来实现以下逻辑块。
@Data
class MyDetails{
private String name;
private String status;
private Integer spreadValue;
private Object value;
...
}
public List<MyDetails> returnValidList(Collection<MyDetails> myDetails){
for (MyDetails myDetail : myDetails){
if (myDetail !=null && myDetail.getValue()!=null){
if (myDetail.getSpreadValue()==3 || myDetail.getSpreadValue()==4){
if (myDetail.getName().equalsIgnoreCase("AUTO") || myDetail.getName().equalsIgnoreCase("HOME")){
result.add(myDetail);
} else {
result.add(myDetail);
}
}
}
return result;
}
}
我尝试了以下代码,但列表大小为零,预期列表大小为 17。任何更正以下代码段的建议。
List<MyDetails> result = myDetails.stream()
.filter(Objects::nonNull)
.filter(obj -> Objects.nonNull(obj.getValue()))
.filter(obj -> obj.getSpreadValue() == 3 || obj.getSpreadValue() == 4)
.collect(Collectors.toList());
您唯一可以做的就是通过 Stream API.
链接filter
调用
List<MyDetails> result = myDetails.stream()
.filter(Objects::nonNull)
.filter(obj -> Objects.nonNull(obj.getValue()))
.filter(obj -> obj.getSpreadValue() == 3 || obj.getSpreadValue() == 4)
.filter(obj -> obj.getName().equalsIgnoreCase("AUTO") || obj.getName().equalsIgnoreCase("HOME"))
.collect(Collectors.toList());
以更复杂的方式,您可能希望将条件提取到单独的变量或方法(返回 Predicate<MyDetails>
)。但是,在高级和可配置过滤的情况下,我建议迭代一个集合可以在应用程序之前先过滤的此类谓词的数量:
// Predicate list
List<Predicate<MyDetails>> predicates = List.of(
Objects::nonNull, // should be always first
obj-> Objects.nonNull(obj.getValue()),
obj-> obj.getSpreadValue() == 3 || obj.getSpreadValue() == 4,
obj-> obj.getName().equalsIgnoreCase("AUTO") || obj.getName().equalsIgnoreCase("HOME")
);
// Reduction using AND. If no predicate is qualified,
// ... a predicate that everything passes through is returned (identity)
Predicate<MyDetails> predicate = predicates.stream()
.reduce(obj -> true, Predicate::and);
// Apply the predicate
List<MyDetails> result = myDetails.stream()
.filter(predicate)
.collect(Collectors.toList());
实现注意事项:
- Stream API 在这种情况下没有任何改进,除非您需要可配置或高级过滤。
- 如果你想有可配置的谓词,使用
LinkedHashMap
并按键过滤不需要的谓词。
还有一些代码审查,只要你的代码看起来很不完整(虽然我尽力格式化它并使其清晰):
- 您的方法中还漏掉了另一个
return
。 private Something value;
在MyDetails
定义中缺失。List<MyDetails>
在方法中未定义(记得你调用getValue()
)。obj.getSpreadValue() == 3 || obj.getSpreadValue() == 4)
和obj.getName().equalsIgnoreCase("AUTO") || obj.getName().equalsIgnoreCase("HOME")
是重构的对象。我建议使用HashSet
和Set::contains
.AUTO
和HOME
名称的条件检查无关紧要,因为 both 分支都会导致将项目添加到列表中。