![](/img/trans.png)
[英]Java Streams concat Streams with Supplier followed by distinct (lazy evaluation behavior)
[英]Using Java 8 Supplier in streams to achieve lazy evaluation
我正在嘗試在像這樣的流中使用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());
}
我認為僅使用標准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;
}
}
也有其他可能性,例如參見此問題 。
但是要當心! 如果添加惰性評估,則您的數據結構是可變的,因此,如果在多線程環境(或並行流)中使用它,請添加同步。
但是,我將使用您的詳細版本。 現在可以清楚地知道它的作用,而且只長了四行。 (在實際代碼中,我希望這四行無關緊要。)
您的第二個變體可以簡化為
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
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.