This week we’re looking at JEP 269: Convenience Factory Methods for Collections as part of the Java 9 series. The Java 9 series looks at some of the JDK Enhancement Proposals (JEPS) hoping to, and confirmed as, making their way into Java 9. Last time we looked at the Segmented Code Cache. This week, we look at the completed quality of life enhancement to “ease the pain of not having collection literals…” by defining APIs to create instances of collections and maps with small numbers of elements.
A collection literal (“a syntactic expression form that evaluates to an aggregate type, such as an array, List, or Map”) would allow the initialisation of a collection with a compact expression. For example creating a new Array in programming language Ruby can be done in the following ways:
new_array = Array.new new_array =  new_array = ["a", "b", "c"] new_array = %w[a b c]
Research proposal JEP 186 looked into whether there could be a design for Java that would be suitable for a future enhancement, such as:
List<Integer> list = #[ 1, 2, 3 ];
If written, it should increase productivity and, with shorter lines of code, increase clarity. The JEP also mentions safety – as the resulting object could be immutable.
However, this may have to wait as value types are coming. Value types would provide JVM infrastructure to work with immutable, reference-free objects – in part to allow for high performance when pairs of return values are required. Among other reasons outlined in March 2014 to put collection literals on hold, Oracle’s Java Language Architect Brian Goetz explained: “[to ask] ‘what would this feature look like’ in a world with value types may well be quite different than in a world without, suggesting it would be questionable to try and do this work before value types”. Collection literals as a language feature need to come after value types. When value types are a feature of Java, however, has not been promised.
Without collection literals, the motivation for JEP 269 is to reduce the overhead in creating a small instance of an unmodifiable set, for example:
Set set = new HashSet<>(); set.add("a"); set.add("b"); set.add("c"); set = Collections.unmodifiableSet(set);
Code example from JEP 269
Currently, library Guava provides a way to initialise an unmodifiable set:
public static final ImmutableSet LETTERS = ImmutableSet.of( "a", "b", "c", "d");
As an interim solution, the work done in the JEP 269 proposal borrows from Guava’s ImmutableXxx classes, but will be much smaller in scale. This is as “the Guava libraries are very useful and general but are perhaps overkill for inclusion into the Java SE Platform”.
What to expect?
APIs will be provided to create small, unmodifiable collections which will be serializable. This reduces overhead as the runtime space will be smaller.
Null elements, keys and values will not be allowed, and elements stored must have proper support for
There will be static factory methods on
Set interfaces, for example:
List.of(a, b, c); Set.of(d, e, f, g);
varargs overload meaning there will be no fixed limit on the size. It will be possible to tune collection instances for smaller size.
Map, there will be a set of fixed-argument methods, up to ten key-value pairs:
Map.of() Map.of(k1, v1) Map.of(k1, v1, k2, v2) Map.of(k1, v1, k2, v2, k3, v3) ...
For larger entries, there will be an API that will create a
Map instance with an arbitrary number of key-value pairs:
Map.ofEntries( entry(k1, v1), entry(k2, v2), entry(k3, v3), // ... entry(kn, vn));
Code examples from JEP 269
It is the hope of the JEP that this will cover a large number of use-cases, and be a good short-term solution until collection literals are re-examined. In the meantime, the concrete classes behind the instances wont be exposed as public APIs. This allows the implementation to change over time without the need to consider backwards compatibility.