RFR(m): 8177290 add copy factory methods for unmodifiable List, Set, Map

Patrick Reinhart patrick at reini.net
Fri Nov 3 05:26:12 UTC 2017

Am 02.11.2017 um 20:08 schrieb Roger Riggs:
> Hi,
> It would also support a more fluent use of the APIs.  Though if we
> start down that road
> it may become littered with convenience methods.  Something to ponder
> for a bit.
One one hand I see your obligation, on the other hand we would open the
chance to write
more optimal implementations for a library implementers though. That
seems to me also
an considerable point here. For instance an unmodifiable List could
basically return a fast
copy of itself here using an internal constructor passing the values
from itself or a Set
implementation has not to check for duplicate entries or similar.


> On 11/1/2017 4:29 PM, Patrick Reinhart wrote:
>> In this case I would prefer a non static copyOf() method on the list
>> to create a unmodifiable list/set/map, where the optimal factory
>> method can be called. This would also solve the problem of a
>> concurrent implementation.
>> -Patrick
>>> Am 01.11.2017 um 21:05 schrieb Louis Wasserman <lowasser at google.com>:
>>> I disagree, actually.  Collections with size zero and one are
>>> significantly more common than bigger collections.
>>> In Guava's immutable collection factories (ImmutableList.of(...)
>>> etc.), we observed a roughly exponential decline in the number of
>>> users of factory methods of each size: if N people created empty
>>> lists, ~N/2 created singleton lists, ~N/4 created two-element lists,
>>> etc.  We got noticeable pushback from RAM-sensitive customers when
>>> we eliminated some specialized singleton collection implementations.
>>> Our experience has been that specializing for N=0 and N=1 does pay
>>> off.  Probably not N=2, though?
>>> On Wed, Nov 1, 2017 at 12:45 PM Patrick Reinhart <patrick at reini.net
>>> <mailto:patrick at reini.net>> wrote:
>>>> Am 01.11.2017 um 20:25 schrieb Stuart Marks
>>>> <stuart.marks at oracle.com <mailto:stuart.marks at oracle.com>>:
>>>> On 10/31/17 5:52 PM, Bernd Eckenfels wrote:
>>>>> Having a List.of(List) copy constructor would save an additional
>>>>> array copy in the collector Which uses 
>>>>> (List<T>)List.of(list.toArray())
>>>> The quickest way to get all the elements from the source collection
>>>> is to call toArray() on it. Some copy constructors (like
>>>> ArrayList's) simply use the returned array for internal storage.
>>>> This saves a copy, but it relies on the source collection's
>>>> toArray() implementation to be correct. In particular, the returned
>>>> array must be freshly created, and that array must be of type
>>>> Object[]. If either of these is violated, it will break the ArrayList.
>>>> The "immutable" collections behind List.of/copyOf/etc. are
>>>> fastidious about allocating their internal arrays in order to
>>>> ensure that they are referenced only from within the newly created
>>>> collection. This requires making an „extra" copy of the array
>>>> returned by toArray().
>>>> An alternative is for the new collection to preallocate its
>>>> internal array using the source's size(), and then to copy the
>>>> elements out. But the source’s
>>>> size might change during the copy (e.g., if it’s a concurrent
>>>> collection) so this complicates things.
>>> I think the array „overhead“ would be only for the cases of zero,
>>> one and two value implementations. That seems to me not worth of
>>> optimizing…
>>>> I think the only safe way to avoid the extra copy is to create a
>>>> private interface that can be used by JDK implementations.
>>>> s'marks
>>> -Patrick

More information about the core-libs-dev mailing list