在Java 8中懒惰地返回第一个非空列表

raf*_*aga 6 java lambda lazy-loading list

我有N个列表从存储库返回数据.我想返回这三个列表中的第一个非空(每个列表执行不同的SQL来获取数据).

问题是我想懒得这样做,所以如果我已经找到了可接受的结果,我就不需要在数据库上执行SQL.我的代码是(修改过的)

@Override
public List<Something> dataService(Data data) {

return firstNonEmptyList(repository.getDataWayOne(data.getParameter()), 
                         repository.getDataWayTwo(data.getParameter()),
                         repository.getDataWayThree(data.getParameter().getAcessoryParameter())
                         Collections.singletonList(repository.getDefaultData(data.getParameter()));

}

@SafeVarargs
private final List<Something> firstNonEmptyList(List<Something>... lists) {
for (List<Something> list : lists) {
  if (!list.isEmpty()) {
    return list;
  }
}

return null;

}
Run Code Online (Sandbox Code Playgroud)

这有效,但它不是懒惰的.有任何想法吗?

shm*_*sel 11

您可以创建供应商流并按照订单顺序对其进行评估,直到找到结果:

return Stream.<Supplier<List<Something>>>of(
            () -> repository.getDataWayOne(data.getParameter()),
            () -> repository.getDataWayTwo(data.getParameter()),
            () -> repository.getDataWayThree(data.getParameter().getAcessoryParameter()),
            () -> Collections.singletonList(repository.getDefaultData(data.getParameter()))
        )
        .map(Supplier::get)
        .filter(l -> !l.isEmpty())
        .findFirst()
        .orElse(null);
Run Code Online (Sandbox Code Playgroud)

每个供应商都定义了如何访问结果集,而不是map()在执行之前实际尝试它.由于filter()并且map()无状态操作,因此将在下一个供应商尝试之前调用每个供应商并验证其结果.如果找到非空结果,则流将立即终止,因为它findFirst()短路的.