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

Louis Wasserman lowasser at google.com
Wed Nov 1 20:05:11 UTC 2017

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> wrote:

> > Am 01.11.2017 um 20:25 schrieb Stuart Marks <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