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

Patrick Reinhart patrick at reini.net
Wed Nov 1 20:29:46 UTC 2017


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