如何向 Supplier<List> 添加值

Posted

技术标签:

【中文标题】如何向 Supplier<List> 添加值【英文标题】:How to add values to Supplier<List> 【发布时间】:2021-09-15 23:48:25 【问题描述】:

我觉得我对供应商用例有一些错误的解释。 这是一个我想为列表添加值的示例。但是当我尝试从供应商那里获取列表时,它显示为空。

Supplier<List<String>> str = ArrayList::new;
        
str.get().add("Hi");
System.out.println(str.get().size());

返回:0

【问题讨论】:

你错过了大局。这不是 Supplier 的用途。检查When we should use Supplier in Java 8? 【参考方案1】:

Supplier&lt;List&lt;String&gt;&gt; 是一个在 get 方法运行时被调用的函数。

在您的情况下,str 类似于以下 lambda 表达式:

Supplier<List<String>> str = () -> new ArrayList<>();

这意味着每次调用str.get(),都会调用函数,并执行主体new ArrayList&lt;&gt;(),因此每次都会产生一个新列表。

如果您希望Supplier 始终返回相同的列表,那么您需要捕获它:

List<String> list = new ArrayList<>();
Supplier<List<String>> str = () -> list;

这样,每次str.get() 运行时,它都会返回它捕获的相同列表。但是,IMO,这似乎不是一个好的做法,只保留对变量的引用而不是将其保留在供应商后面(这意味着产生值的函数)似乎是正确的。

【讨论】:

还可以选择创建一个新的装饰供应商,该供应商将始终对创建的列表执行添加操作 Supplier&lt;List&lt;String&gt;&gt; tmp = str; str = () -&gt; List&lt;String&gt; list = tmp.get(); list.add("Hi"); return list; ; 【参考方案2】:

str.get() 的每次调用都会实例化一个新的List,该List 将为空。

您对str.get() 的两次调用会返回两个不同的实例。您向第一个 List 添加了一个元素,但第二个 List 为空。

如果你想访问它,你必须存储对创建的List 的引用:

List<String> list = str.get();
list.add("Hi");
System.out.println(list.size());

【讨论】:

Eran,谢谢你的解释。我的用例是这样的。我必须在一个方法中声明几种类型的列表。现在我想让它们变得懒惰,所以用供应商把它们包起来。如何在 Supplier get() 调用中引用列表。 @mitali 如果不查看实际代码,很难理解您到底需要什么。通常,每次调用Supplierget() 时,都必须在某处存储对创建的List 的引用。否则没用。

以上是关于如何向 Supplier<List> 添加值的主要内容,如果未能解决你的问题,请参考以下文章

java8中stream().collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator)说明

C#如何向List<>中添加多个元素?

Supply

延迟方法的调用---排列数字的大小(Supplier)

java8常用函数式接口 Supplier ConsumerPredicateFunction总结

java函数式编程之Supplier