我试图在像这样的流中使用Supplier实现懒惰的评估
public static void main(String[] args) {
Supplier<List<String>> expensiveListSupplier= getExpensiveList();
getList().stream()
.filter(s -> expensiveListSupplier.get().contains(s))
.forEach(System.out::println);
}
private static Supplier<List<String>> getExpensiveList() {
return () -> Stream
.of("1", "2", "3")
.peek(System.out::println)
.collect(Collectors.toList());
}
private static List<String> getList() {
return Stream.of("2", "3")
.collect(Collectors.toList());
}
但这将为列表中的每个元素调用getExpensiveList()方法。 我试图不要太冗长,也不想写这样的东西,即不添加空支票和东西。
public static void main(String[] args) {
Supplier<List<String>> expensiveListSupplier = getExpensiveList();
List<String> list = getList();
if (!list.isEmpty()) {
List<String> expensiveList = expensiveListSupplier.get();
list.stream()
.filter(expensiveList::contains)
.forEach(System.out::println);
}
}
private static Supplier<List<String>> getExpensiveList() {
return () -> Stream
.of("1", "2", "3")
.peek(System.out::println)
.collect(Collectors.toList());
}
private static List<String> getList() {
return Stream.of("2", "3")
.collect(Collectors.toList());
}
答案 0 :(得分:2)
我认为仅使用标准Java类是不可能的。但是您可以编写自己的惰性评估器并使用它,例如(未试用):
public class LazyValue<T> implements Supplier<T> {
private T value;
private final Supplier<T> initializer;
public LazyValue(Supplier<T> initializer) {
this.initializer = initializer;
}
public T get() {
if (value == null) {
value = initializer.get();
}
return value;
}
}
还有其他可能性,例如参见this question。
但是要当心!如果添加惰性评估,则您的数据结构是可变的,因此,如果在多线程环境(或并行流)中使用它,请添加同步。
但是,我将使用您的详细版本。现在可以清楚地知道它的作用,而且只长了四行。 (在实际代码中,我希望这四行无关紧要。)
答案 1 :(得分:2)
您的第二个变体可以简化为
List<String> list = getList();
if(!list.isEmpty()) {
list.stream()
.filter(getExpensiveList().get()::contains)
.forEach(System.out::println);
}
它使Supplier
的使用毫无意义,因为仅当列表为非空时,才对getExpensiveList()
进行调用。但是另一方面,这就是您可以获得的最大懒惰,即在另一个列表为空时不请求昂贵的列表。无论哪种情况,当列表不为空时,都会为第一个元素请求昂贵的列表。
如果昂贵的清单可能很大,则应使用
List<String> list = getList();
if(!list.isEmpty()) {
list.stream()
.filter(new HashSet<>(getExpensiveList().get())::contains)
.forEach(System.out::println);
}
相反,请避免重复线性搜索。或重新设计getExpensiveList()
首先返回一个Set
。