Collectors update

Remi Forax forax at univ-mlv.fr
Tue Jan 29 16:34:42 PST 2013


On 01/30/2013 12:22 AM, Brian Goetz wrote:
>>> 4.  Rejigger Partition to return an array again, with an explicit
>>> lambda (which will likely be an array ctor ref) to make the array.
>>> Eliminated the silly Partition class.
>>
>> Please don't do that, it's pure evil.
>
> The silly Partition class was also evil.  We're in the "lesser of 
> evils" business here.
>
>>    public static<T> Collector<T, Collection<T>[]>
>> partitioningBy(Predicate<T> predicate, IntFunction<Collection<T>[]>
>> arraySupplier) {
>>
>> in order to call this method users have to send a lambda that creates an
>> array of parametrized type something which will be unsafe (the only way
>> to get type safety is to create a class that inherits from Collection
>> and to provide a type argument something like class Foo extends
>> ArrayList<String> {}) so while the code of the library is typesafe, no
>> user code will never be typesafe.
>
> Yes, let's have this discussion.  The above is true, but is this 
> really a problem? 

yes, it is.
Arrays of parametrized type are unsafe to create unless you can subclass 
the component type.
By example,
   enum Foo { }
   Enum<Foo>[] array = Foo.values();
is safe. but
   Enum<Foo>[] array = new Enum<>[2];
is not safe, and should even not compile because you can not use the 
diamond syntax on an array.

> The array is simply a box for carrying the result back.  The typical 
> use case will be:
>  - call partition
>  - scoop out the two collections / reductions / whatever
>  - throw away the box
>
> So the box is intended to be a short-lived container (essentially a 
> workaround for the lack of tuples.)

if you want a tupe, just create a class Tuple (with a private constructor),
the other solution is to not include partioningBy in jdk8 and wait 9.

Now, why it's unsafe, let say we have:
   Collection<String>[] csa = stream.collect(Collectors.partioningBy( ...));
one can write
   Object[] array = csa;
   array[0] = Arrays.asList(1);
and later
   String s = csa[0].get();   // ClassCastException

> This is not the same case as Stream.toArray.

no, it's not. toArray can be used in a safely manner or not. 
partionningBy is (almost) never safe.

>
>> and BTW, the IntFunction will be always called with 2 as argument.
>
> Yes.  Is that bad?
>

why not using a Supplier ?

Rémi



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