Into

Remi Forax forax at univ-mlv.fr
Wed Dec 26 11:52:21 PST 2012


On 12/26/2012 07:38 PM, Brian Goetz wrote:
> Let's try to separate some things here.
>
> There's lots of defending of into() because it is (a) useful and (b) 
> safe.  That's all good.  But let's see if we can think of these more 
> as functional requirements than as mandating a specific API (whether 
> one that happens to be already implemented, like into(), or the newly 
> proposed ones like toEveryKindOfCollection().)
>
> Into as currently implemented has many negatives, including:
>  - Adds conceptual and API surface area -- destinations have to 
> implement Destination, the semantics of into are weird and unique to into
>  - Will likely parallelize terribly
>  - Doesn't provide the user enough control over how the into'ing is 
> done (seq vs par, order-sensitive vs not)
>
> So let's step back and talk requirements.
>
> I think the only clear functional requirement is that it should be 
> easy to accumulate the result of a stream into a collection or similar 
> container.  It should be easy to customize what kind of collection, 
> but also easy to say "give me a reasonable default." Additionally, the 
> performance characteristics should be transparent; users should be 
> able to figure out what's going to happen.
>
> There are lots of other nice-to-haves, such as:
>  - Minimize impact on Collection implementations
>  - Minimize magic/guessing about the user's intent
>  - Support destinations that aren't collections
>  - Minimize tight coupling of Stream API to existing Collection APIs
>
> The current into() fails on nearly all of these.

Brian, you confound the concept of into() with it's current implementation.
  - Minimize impact on Collection implementations
    => fail because destination interface says that destination should 
have a method add(Stream)
          but this is not a requirement, destination can use already 
existing add/addAll
  - Minimize magic/guessing about the user's intent
    => fails, due to the implementation
  - Support destinations that aren't collections
    => works
  - Minimize tight coupling of Stream API to existing Collection APIs
    => part of the problem is point 1, the other part is that loosely 
couple will come with a price for users
          like requiring them to specify too many parameters for common 
use cases.

for me the requirements are (in that order)
   - support classical collections in a way that is always thread safe
   - support destination that are not collections
   - minimize coupling with Collection API

if you want to compare your tabulator with into, into has to be 
correctly specified,
I think, it should be something like this:
   into(Supplier<Destination<T>> supplier)
with the interface Destination defined like this
   interface Destination<T, D extends Destination<? extends T, D>> {
     boolean add(T element);
     boolean addAll(D destination);
   }

example of usages:
   stream.into(ArrayList::new);   // with Collection<E> implements 
Destination<E, Collection<E>>

with that, I see your tabulator as a more fine grain API that into() but 
that requires users to send more information.

Rémi



More information about the lambda-libs-spec-observers mailing list