我有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;
}
这很有效,但它并不懒惰。有什么想法吗?
答案 0 :(得分: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);
每个供应商都定义了如何访问结果集,而不是在执行map()
之前实际尝试它。由于filter()
和map()
是stateless操作,因此在尝试下一个供应商之前,将调用每个供应商并验证其结果。如果找到非空结果,则流将立即终止,因为findFirst()
为short-circuiting。
答案 1 :(得分:3)
如果溪流不是你的一杯茶,你仍然可以使用lambdas来实现你想要的东西,只需对原始代码进行一些细微的修改。
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;
}