如何优雅地重复过滤java流直到找到单个结果?

gel*_*d0r -1 java java-stream

我有以下函数,它尝试逐步缩小输入集合的范围,直到找到单个元素,即,当找到单个项目时,过滤应该停止,因为应用附加过滤器可能会导致根本不匹配。

public List<MyObject> determinePotentialCandidates(List<MyObject> allCandidates) {

        List<MyObject> candidates = allCandidates.stream()
                                                 .filter(this::firstCondition)
                                                 .toList();

        if (candidates.size() > 1) {

            candidates = candidates.stream()
                                   .filter(this::secondCondition)
                                   .toList();

            if (candidates.size() > 1) {

                candidates = candidates.stream()
                                       .filter(this::thirdCondition)
                                       .collect(Collectors.toList());
            }
            
            // ... and so on
        }

        logResult(candidates);
        return candidates;
    }
Run Code Online (Sandbox Code Playgroud)

由于随着每个附加嵌套级别的增加,这变得更难阅读,我想知道是否有更简洁的方法来编写它。

优选地,该方法应该最多执行每个过滤步骤一次(尽管输入大小很小且过滤成本低廉——这可能可以对同一输入执行多次)并且包含单个出口点。

hev*_*ev1 5

您可以将所有条件放入 a 中List并对其进行循环,在每次迭代中应用一个过滤器,直到只剩下一个元素。

List<Predicate<MyObject>> conditions = List.of(this::firstCondition, this::secondCondition, this::thirdCondition /*...*/ );
for(int i = 0; i < conditions.size() && allCandidates.size() > 1; i++)
    allCandidates = allCandidates.stream().filter(conditions.get(i)).toList();
// Note: you may need to check if the list is empty here
return allCandidates;
Run Code Online (Sandbox Code Playgroud)