JEP 186: Collection Literals
Tom Hawtin
tom.hawtin at oracle.com
Thu Jan 23 10:11:58 PST 2014
[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.)
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();
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
More information about the lambda-dev
mailing list