说我有一个字符串列表,我想将这些字符串用作流利的构建器的输入。
List<String> scripts;
//initialize list
ScriptRunnerBuilder scriptRunnerBuilder = new ScriptRunnerBuilder();
BiFunction<String,ScriptRunnerBuilder,ScriptRunnerBuilder> addScript =
(script,builder) -> builer.addScript(script);
scriptRunnerBuilder = scripts.stream.map(script ->
addScript.apply(script,scriptRunnerBuilder)).......
scriptRunnerBuilder.build();
我可以使用哪个终端操作,以便对列表中的所有元素调用addScript函数?
问题在于ScriptRunnerBuilder是不可变的,因此ScriptRunnerBuilder.addScript()返回一个新的ScriptRunnerBuilder对象,而不是修改现有对象-因此我不能只给我们一个foreach。
我的意图是携带addScript()调用的结果,并将其用作流中下一个元素的输入
答案 0 :(得分:5)
最简单的方法应该是:
// create your builder
ScriptRunnerBuilder builder = new ScriptRunnerBuilder();
// add all scripts
scripts.forEach(script-> builder.addScript(script))
build results
scriptRunnerBuilder.build();
因为构建器聚合了所有数据,并且您已经在for lambda外部创建了数据,所以可以直接访问它。这将导致更少的代码和相同的结果。
或按照@Holger的建议:
scripts.forEach(builder::addScript);
答案 1 :(得分:2)
使用forEach
代替map
,并且不再分配流的结果
scripts.forEach(script -> addScript.apply(script,scriptRunnerBuilder));
答案 2 :(得分:1)
我可以使用reduce操作,但这是不必要的,因为我们不合并结果
合并正是您的工作。
您将List<String>
到ScriptRunnerBuilder
的所有脚本组合在一起了吗?
我同意@Beri不带流的解决方案可能是最简单的。但是,reduce(identity, accumulator, combiner)
方法也有一种方法,您无需在之前创建ScriptRunnerBuilder
:
ScriptRunnerBuilder builder = scripts.stream()
.reduce(new ScriptRunnerBuilder(), ScriptRunnerBuilder::addScript, (b1, b2) -> b1);
查看更多:Why is a combiner needed for reduce method that converts type in java 8
更新要不依赖于combiner
没有被顺序流调用并使其与并行流一起工作这一事实,您必须实现真正的combiner
。
如果您可以添加覆盖的方法addScript(ScriptRunnerBuilder otherBuilder)
,则reduce
如下所示:
.reduce(new ScriptRunnerBuilder(), ScriptRunnerBuilder::addScript,
ScriptRunnerBuilder::addScript)