please review draft JEP: Convenience Factory Methods for Collections

Remi Forax forax at univ-mlv.fr
Sat Jul 19 09:04:27 UTC 2014


On 07/19/2014 01:36 AM, Stuart Marks wrote:
> On 7/18/14 2:17 AM, Michael Kay wrote:
>> On 18 Jul 2014, at 10:09, Wang Weijun <weijun.wang at oracle.com> wrote:
>>> A .with(k, v) to create a new immutable map with an extra pair.
>>
>> Yes, that's the same as my A.add(k,v) -> A proposal.
>>
>> Works whether A is mutable or immutable.
>
> I don't think we want to have a Map.add(k,v) instance method (or 
> default method) for immutable maps or for constructing them.
>
> For a fast, compact, immutable map implementation, the only way to 
> implement Map.add() would be to copy the entire contents plus the 
> additional pair into a new map. For creating maps with small numbers 
> of entries, this isn't really a big deal, but if you have something like
>
>     Map.of()
>        .add(k0, v0)
>        .add(k1, v1)
>          ...
>        .add(kN, vN);
>
> this would result in O(N^2) performance and space allocation, though 
> most of the allocated space is garbage.
>
> Of course, one could avoid the copying overhead by making the 
> immutable maps persistent (i.e., sharing their unmodified portions) 
> but that is an entirely different discussion.
>
> I kind of think you're after the ability to chain the method calls. 
> This is certainly convenient and has no arbitrary restrictions on the 
> number of elements. To do something like this we'd put the chainable 
> methods on a builder instead:
>
>     Map.builder()
>        .add(k0, v0)
>        .add(k1, v1)
>          ...
>        .add(kN, vN)
>        .build();
>
> This is somewhat more cluttered than the Map.of(Entry...) approach:
>
>     Map.of(
>         entry(k0, v0),
>         entry(k1, v1),
>           ...
>         entry(kN, vN));
>
> but it might make up for it with flexibility. I hesitate a bit to 
> pursue the builder approach, because it can easily get bogged down 
> with additional features, but the special considerations for Map might 
> require it.
>
> s'marks

You can combine these 2 approachesi using a Ruby like builder approach 
with a lambda,
which provide a builder object (so static method call are replaced by 
instance method call) avoiding the creation of too many entry objects
Map.of(b -> b
         .entry(k0, v0)
         .entry(k1, v1)
           ...
         .entry(kN, vN))

cheers,
Rémi




More information about the core-libs-dev mailing list