如何将流用于具有多个条件检查的逻辑?

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") 是重构的对象。我建议使用 HashSetSet::contains.
  • AUTOHOME 名称的条件检查无关紧要,因为 both 分支都会导致将项目添加到列表中。