JEP 186: Collection Literals

John Hendrikx hjohn at xs4all.nl
Tue Jan 14 17:47:16 PST 2014


I'm very much in favor of either:

- a full fledged extensible system that will work with any Class that 
provides specific (optionally static) constructors/methods
- just some helper methods where you'd expect them, ie: 
ArrayList.of("A", "B", "C"), and some extra magic for maps that deal 
with their arguments in an odd/even fashion (not type unfortunately)

Other than that, I could voice some crazy idea like supporting multiple 
ellipsis / parameter groups:

   HashMap(K... keys, V... values) {}  // constructor

   new HashMap<String, Integer>("A", 2, "B", 3, "C", 4);

Or to only add a bit of syntactic sugar, in combination with an 
annotation/interface for value-holder type classes (or for special 
initialization constructors) and additional constructors for the 
Collection classes:

1) Add the following constructors to HashMap and ArrayList (and others):

   @Initializer HashMap(Entry<K,V>... entries)
   @Initializer ArrayList(Value<T>... values)

where Entry and Value are classes with a public constructor:

    @ValueHolder
    class Entry<K,V> {
       Entry(K k, V v) {}
    }

   @ValueHolder
   class Value<T> {
       Entry(T t) {}
    }

2) Add the following syntax sugar:

    HashMap<String, Integer> map1 = ({"A", 1}, {"B", 2});
    HashMap<String, ArrayList<Integer>> map2 = ({"A", {1, 2, 3, 4}}, 
{"B", {2, 4, 6, 8}});

transforms to:

    HashMap<String, Integer> map = new HashMap<>(new Entry<String, 
Integer>("A", 2), new Entry<String, Integer>("B", 3));
    HashMap<String, Integer> map = new HashMap<>(new Entry<String, 
ArrayList<Integer>>("A", new ArrayList<Integer>(new Value(1), new 
Value(2), new Value(3), new Value(4))), new Entry<String, 
ArrayList<Integer>>("B", new ArrayList<Integer>(new Value(2), new 
Value(4), new Value(6), new Value(8))));

The transformation above is fully driven by the types specified on the 
lhs and the annotation on the constructors and/or their value-holders.  
It could basically be done right now (with IDE support), apart from the 
needed changes to HashMap and ArrayList.  It is fairly flexible I think 
as well, and certainly does not need to be limited to Collection 
classes, ie:

    HBox hbox = ({new Button("OK"), new Button("Cancel")});

transforms to:

    HBox hbox = new HBox(new HBox.ValueHolder(new Button("OK")), new 
HBox.ValueHolder(new Button("Cancel")));

where HBox.ValueHolder is whatever HBox decides to use for its value-holder.

This is hardly light-weight though, and it would be worth investigating 
if this could be done more direct or to see if the compiler could handle 
optimizing away the value holders.

--John

On 14/01/2014 18:23, Brian Goetz wrote:
> This is a very valid point, and one that has been raised before -- that
> maybe this doesn't need a language feature, that maybe simply some
> library changes would be enough.
>
> In fact, since the goal at this point is to discuss whether we should
> move forward or not with the /exploration/ of the language feature, let
> me restrict the discussion to this point: is this something that needs a
> language feature, or would library support be enough?  Bear in mind that
> the cost of even a simple language feature is probably 100x that of a
> comparable library feature, cost-benefit is an important consideration.
>
> On 1/14/2014 12:02 PM, Klaus Malorny wrote:
>> On 14.01.2014 17:33, Nick Williams wrote:
>>    >  I think we should also try to keep the Java Unified Expression Language in
>>    >  mind while designing this. Java EE 7 added lambda expressions to JUEL. Can
>>    >  you imagine how confusing it would have been if they had defined a different
>>    >  lambda syntax than Java 8? They didn't, though. They made the syntax mirror
>>    >  Java 8 lambdas.
>>    >
>>    >  JUEL also has collection literals now, and I think it would be foolish to
>>    >  define a literal syntax different than that defined in JUEL. It will make
>>    >  developers' lives more difficult. The JUEL syntax is simple and I think it
>>    >  would work perfectly in Java as well:
>>    >
>>    >  List: [ 1, 2, 3 ] Set: { 1, 2, 3 } Map: { "one" : 1, "two" : 2, "three" : 3
>>    >  }
>>    >
>>    >  If we, for example, make Lists use curly braces in Java when they already use
>>    >  square brackets in JUEL, that would be unfortunate.
>>    >
>>    >  Nick
>>    >
>>
>>
>> Hi,
>>
>> if I may add my two cents: I have solved the problem for me by
>>
>> - having a static setOf (...) method to construct sets, which
>>      is imported via static import if need be
>> - having a static mapOf (key, value) method which is the start
>>      of a call chain, ending with map (), which returns the constructed
>>      map,
>>
>>      e.g. Map<String, Integer>  map = mapOf ("one", 1).put ("two", 2).
>>             put ("three", 3).map ();
>>
>> Overloaded and alternative methods allow me to create unmodifiable sets and
>> maps, including EnumMaps, also to perform some additional checks for EnumMaps
>> (e.g. whether all keys occur). Similar could be done for lists, of course.
>>
>> So while I do not dislike collection literals, I just want to point out that the
>> keyboard typing benefit isn't that great IMHO.
>>
>> Regards,
>>
>> Klaus
>>



More information about the lambda-dev mailing list