Troy Daniels
Troy Daniels

Reputation: 3598

Collect/reduce on a stream when no combine function exists

I have a collection where I would like to use the stream API to reduce it to a single value. It looks like collect or reduce would work well, except that both of them want a combiner object to merge parallel results. In my case, I do not have a combining operation.

There will not be a lot of elements in the stream, so I am happy to have it run serially. Is there a way to handle this?

If my stream contains 1,2 and 3, I want to do the equivalent of

result = new Foo().foo(1).foo(2).foo(3);

It seems that

result = stream.reduce(new Foo(),
                       (foo, ele) -> foo.foo(ele),
                       null);

would likely work, but at some point, some change (slightly longer list, new Java version) the combiner will get called and that will break.

I am returning a different type, so reduce(BiFunction) will not work for me.

Upvotes: 4

Views: 906

Answers (2)

Calculator
Calculator

Reputation: 2789

If you prefer to stick to a stream, you could use forEachOrdered as it is allowed to be stateful:

AtomicReference<Foo> foo = new AtomicReference<>(new Foo());
stream.forEachOrdered(ele -> foo.updateAndGet(f -> f.foo(ele)));        
Foo result = foo.get();

Upvotes: 1

Andy Turner
Andy Turner

Reputation: 140328

I would just use a loop over the elements of the collection:

Foo result = new Foo();
for (int ele : collection) {
  result = result.foo(ele);
}

This is easy to read, of similar verbosity to the streams approach, and you don't have to worry about its behaviour changing unexpectedly because of dark voodoo in the Streams library.

Upvotes: 2

Related Questions