简体   繁体   中英

Terminal operation to evaluate intermediate operation

Let says i have a list of strings and i want to use those strings as input to a fluent builder.

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();

which terminal operation can i use so that the addScript function gets called for all elements in the list?

The issue is that the ScriptRunnerBuilder is immutable whereby ScriptRunnerBuilder.addScript() returns a new ScriptRunnerBuilder object rather than modifying existing – so i can't just us a foreach.

My intentions are to carry the result of the addScript() call and use that as input for the next element in the stream

In simplest way this should:

// create your builder
ScriptRunnerBuilder builder = new ScriptRunnerBuilder();

// add all scripts
scripts.forEach(script-> builder.addScript(script))

build results
scriptRunnerBuilder.build();

Because builder aggregates all data, and you have created it outside forEach lambda, you can access it directly. This will lead to less code and same result.

Or as @Holger suggested:

scripts.forEach(builder::addScript);

使用forEach而不是map并且不再分配流的结果

scripts.forEach(script -> addScript.apply(script,scriptRunnerBuilder));

i could use reduce operation but that is unnecessary as we are not combining results

Combining is exactly what you are doing. You combine all scripts from List<String> to ScriptRunnerBuilder aren't you?

I agree that the @Beri's solution without stream probably is the simplest. But also there is a way with reduce(identity, accumulator, combiner) method where you don't need to create ScriptRunnerBuilder before:

ScriptRunnerBuilder builder = scripts.stream()
        .reduce(new ScriptRunnerBuilder(), ScriptRunnerBuilder::addScript, (b1, b2) -> b1);

See more: Why is a combiner needed for reduce method that converts type in java 8

Update To not to rely on the fact that combiner not being invoked for sequential stream and to make it works with parallel one you have to implement the real combiner .

If you could add an overrided method addScript(ScriptRunnerBuilder otherBuilder) then the reduce will look like:

.reduce(new ScriptRunnerBuilder(), ScriptRunnerBuilder::addScript, 
        ScriptRunnerBuilder::addScript)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM