JEP 186: Collection Literals
Zhong Yu
zhong.j.yu at gmail.com
Thu Jan 23 12:53:36 PST 2014
On Thu, Jan 23, 2014 at 12:11 PM, Tom Hawtin <tom.hawtin at oracle.com> wrote:
> [These are my own opinions.]
>
> Pure library vs language+library implementation. I think there's two
> aspects here.
>
> Current bytecode for varargs is quite verbose, and the JVM has issues
> with long bytecode. Though this could be treated as an orthogonal issue
> or ignored.
>
> The other aspect is syntax.
>
> import static java.util.Lists.list;
> List<Thing> things = list(x, y, z);
>
> vs
>
> List<Thing> things = [x, y, z]
>
> I think the latter is significantly cleaner and removes duplication.
> (Type of collection literal is based on the target type.)
I on the other hand feel very uncomfortable if the same literal means
very different things in different contexts - it could be a List, a
Set, a Person, or a Dog. Inferring the meaning of the literal would
become a burden, at least for unfamiliar types - what does this mean:
`Dog dog = [blah, blah];`? Such code is not a good way to communicate
ideas between programmers.
Using words to express meanings is better than using symbols - if it
doesn't become too verbose. List.of(x,y,z) means a list of x, y, z,
simple and clear. The wordiness of Java programs makes them easier to
understand.
If we must introduce literals, I would prefer their meanings to be
context free - [x,y,z] means an immutable list, that is it.
>
> For maps this is more clear cut.
>
> import static java.util.Maps.map;
> import static java.util.Maps.entry;
> Map<Key,Value> things = map(entry(k, v), entry(l, w), entry(m, x));
>
> vs
>
> Map<Key,Value> things = [[k, v], [l, w], [m, x]]
>
> This works out due to the benefits of static [target] typing.
>
> Assuming general, the syntax above would need some kind of language
> addition to the type. (A static field is not enough.) Perhaps something
> based on constructor syntax:
>
> public interface List<T> ... {
> List[T... values] {
> return
> values.length==0 ? Collections.emptyList() :
> values.length==1 ? new SingletonImmutableList<>(value[0]) :
> new ImmutableList<>(values);
> }
>
> Whilst we are in this area, we still have a lot of redundancy
> constructing objects where the type is 90% obvious. As in:
>
> List<Thing> things = new ArrayList<>();
>
> should be:
>
> List<Thing> things = new();
I think we should almost *never* declare a weaker type on
non-publicized variables, like
List<Thing> things = new ArrayList<>();
instead, we should almost always declare the most specific type, like
ArrayList<Thing> things = new ArrayList<>();
I don't want to start an argument about this issue here; it's just
that, if one adheres to the 2nd style, he'll never need
List<Thing> things = new();
which seems ambiguous, requiring further effort in understanding;
instead, he'll only ever do
ArrayList<Thing> things = new();
which seems very clear in its meaning.
>
> or
>
> List<Thing> things = {};
>
>
> Moving on. There are broadly two security/robustness problems that come
> up with collections and arrays.
>
> Firstly, when a collection is passed between objects it requires an
> explicit copy as the receiver cannot trust that it wont be subsequently
> mutated or has a non-default implementation. java.util collection types
> are bad when they leak into parameters. Immutability makes collections
> safe-by-default for this aspect.
>
> Secondly, collections and arrays may behave badly with respect to
> equality (including hashCode and compareTo). Unfortunately there is
> tradition of not making equals and hashCode final for reference types
> (particularly in interfaces). As the like of List.indexOf mandate use of
> equals we need to switch to non-complying implementations
> (IdentityArrayList) to keep safe. It may therefore, make sense to be
> able to select default implementation type on type of "generic argument".
>
> Set<String> strs = [ "str" ]; // an ImmutableHastSet
> Set<JWindow> windows = [ window ]; // an IdentityImmutableHashSet
>
> Also applies to Comparable, so may have ImmutableTreeHashSet<String>
> (guaranteed O(log n) worst-case sustained performance).
>
> Subclassable or otherwise mutable value types are a basket case. Nothing
> can be done for them, other than an assisted @Deprecated.
>
> Tom
>
Zhong Yu
More information about the lambda-dev
mailing list