Allowing wrapping/transforming of the final result of Stream.collect()

Graham Allan grundlefleck at gmail.com
Tue Apr 16 00:43:11 PDT 2013


Hi all,

I found a past discussion on this mailing list regarding how to obtain a
new immutable collection from a Stream[0], while looking for a solution to
the more general problem of wrapping/transforming the terminal output from
a Stream into a completely different type. In that thread the solution
prescribed was to implement Stream.Destination, and pass that to Stream's
into() method.

AFAICT Stream's into() has been completely superceded by collect(), and
Stream.Destination does not exist in b83.

Does an equivalent now exist with collect()? I could not find an obvious
way to do this, as both accumulator and combiner are expected to operate on
elements or partial results while collecting is in progress, but are not
given the chance to transform the final result.

If there is no equivalent, are there plans to add one? It would be a shame
to miss this out, when I imagine it would be well used, not just for
immutable collections, but also their cousins, the unmodifiable wrappers,
as well as synchronized wrappers, and creating sets from maps
(Collections.newSetFromMap, a common way to obtain a concurrent hash
set[1]).

Another pattern that I use is to take an immutable Collection<T> and wrap
it with my own type to provide methods in the domain language, e.g.:

    Trades trades = new Trades(Arrays.asList(trade1, trade2, ...));
    ...
    Date dateOfEarliest = trades.earliest().getTradedAtDate();

where the implementation of earliest() internally uses collection-like
operations (e.g. min operation with a comparator) but hides them behind a
method expressed in the domain language. I would like, but am currently
unable, to produce a new Trades() instance at the end of the collect()
method. The point of this example is that while we can talk of unmodifiable
and synchronized wrappers, etc, which could be provided in the JDK, this is
a use case that would be impossible for the JDK to provide.

There's a couple of problems I understand may occur:
 - such a method would have to be provided as part of the terminal
operation on a Stream, I don't see how it could come before collect()
 - there's already several forms of collect(), another version adding a
method with another parameter to provide the final conversion would spend
some of the complexity budget
 - I don't know that the generics on such a parameter could work, would it
be able to capture the type of the combiner as the input to a terminator
function, with a different generic type for the result?

Also, I understand that there will always be a workaround, e.g.:

   Trades trades = new
Trades(collectionOfTrades.stream().filter(...).collect(...));

... but it would be nice to read left-to-right, top-to-bottom for the
entire operation, as promoted by the rest of the Streams API.



Cheers,
Graham



[0]
http://openjdk.5641.n7.nabble.com/Working-with-immutable-collections-td105112.html
[1]
http://stackoverflow.com/questions/6992608/why-there-is-no-concurrenthashset-against-concurrenthashmap


More information about the lambda-dev mailing list