RFR(s): 8060192: Add default method Collection.toArray(generator)

Peter Levart peter.levart at gmail.com
Sun Jun 17 08:50:58 UTC 2018


Hi Stuart,

On 06/15/18 03:02, Stuart Marks wrote:
> Comparing this to the type token alternatives, for simple tasks like 
> converting Collection<String> to String[], things are about equal:
>
>     toArray(String[]::new)
>     toArray(String.class)
>     toArray(String[].class)
>
> However, things are hairier if the element type of the collection is 
> generic, such as Collection<List<String>>. The result type is a 
> generic array List<String>[]. Using class literals or array 
> constructor references will necessitate using an unchecked cast, 
> because none of these can be used to represent a generic type.
>
> However, it's possible to use a method reference to provide a properly 
> generic IntFunction. This would enable the toArray(generator) method 
> to be used without any unchecked casts. (The method it refers to might 
> need have an unchecked cast within it, though.) Such a method could 
> also be reused for the corresponding Stream.toArray(generator) method.
>
> For these reasons I'd like to proceed with adding toArray(generator) API. 

It's a little strange that the generator function is used to construct 
an empty array (at least in the default method, but overrides will 
likely do the same if they want to avoid pre-zeroing overhead) in order 
to just extract the array's type from it. Someone could reasonably 
expect the provided function to be called with the exact length of 
needed array. The Collection.toArray(T[]) at least gives user an option 
to actually fully use the provided array, if user provides the correct 
length. The argument about using (and re-using) a method so that a 
method reference can be passed to the method without any unchecked casts 
is equally true for any of the 3 alternatives shown - the method itself 
might need unchecked casts, but its usage not:

static List<String>[] array(int len)
static Class<List<String>> elementType()
static Class<List<String>[]> arrayType()


But I can see that you want to align the API with Stream.toArray, while 
still providing the optimal implementation. It's just that the API 
doesn't fit the usecase. The function approach makes more sense in the 
Stream API where it is explicitly explained that it may be used to 
construct arrays needed to hold intermediary results of partitioned 
parallel execution too, but in Collection API it is usually the case to 
just provide a copy of the underlying data structure in the most optimal 
way (without pre-zeroing overhead) and for that purpose, 2nd and 3rd 
alternatives are a better fit.

Suppose Stream took a different approach and used the 2nd or 3rd 
approach (which is universal). Would then Collection API also get the 
same method?


Regards, Peter



More information about the core-libs-dev mailing list