Return Java 8 中第一个懒惰的非空列表

Return first non empty list lazyily in Java 8

我有 N 个列表 return 来自存储库的数据。我想 return 这三个列表中的第一个非空列表(每个执行不同的 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;

}

这行得通,但并不懒惰。有什么想法吗?

您可以创建一个供应商流并按遇到的顺序对其进行评估,直到找到结果:

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);

每个供应商都定义了如何访问结果集,在执行 map() 之前不会实际尝试访问。因为 filter()map()stateless operations, each supplier will be called and its result validated before the next one is attempted. If a non-empty result is found, the stream will terminate immediately, because findFirst() is short-circuiting.

如果流不是您的菜,您仍然可以使用 lambda 来实现您想要的,只需对原始代码稍作修改。

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()))
        );
}

private final List<Something> firstNonEmptyList(Supplier<List<Something>>... listSuppliers) {
    for (Supplier<List<Something>> supplier : listSuppliers) {
        List<Something> list = supplier.get();
        if (!list.isEmpty()) {
            return list;
        }
    }
    return null;
}