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;
}
我有 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;
}