Sormuras Sormuras - 1 year ago 70
Java Question

Usage of Java 9 collection factories

In the context of the comments and answers given at List.of() or Collections.emptyList() and List.of(...) or Collections.unmodifiableList() I came up with two following rules of thumb (which also apply to

factories accordingly).

  1. Don't replace all occurrences

Keep using
for readability and when e.g. initializing lazy field members like:

class Bean {
private List<Bean> beans = Collection.emptyList();
public List<Bean> getBeans() {
if (beans == Collections.EMPTY_LIST) { beans = new ArrayList<>(); }
return beans;

  1. Use new factories as method argument builders

Use new factories
and variants as quick and less-to-type version, when calling an executable with
parameter(s). Here are my current substitution patterns:

Collections.emptyList() --> List.of()
Collections.singletonList(a) --> List.of(a)
Arrays.asList(a, ..., z) --> List.of(a, ..., z)

In a fictional usage of
, the following lines

Collections.indexOfSubList(Arrays.asList(1, 2, 3), Collections.emptyList());
Collections.indexOfSubList(Arrays.asList(1, 2, 3), Collections.singletonList(1));
Collections.indexOfSubList(Arrays.asList(1, 2, 3), Arrays.asList(1));
Collections.indexOfSubList(Arrays.asList(1, 2, 3), Arrays.asList(2, 3));
Collections.indexOfSubList(Arrays.asList(1, 2, 3), Arrays.asList(1, 2, 3));

will read

Collections.indexOfSubList(List.of(1, 2, 3), List.of());
Collections.indexOfSubList(List.of(1, 2, 3), List.of(1));
Collections.indexOfSubList(List.of(1, 2, 3), List.of(1));
Collections.indexOfSubList(List.of(1, 2, 3), List.of(2, 3));
Collections.indexOfSubList(List.of(1, 2, 3), List.of(1, 2, 3));

Do you (dis-)agree?

Answer Source


First of all, it is important to note that the collection factories return immutable variants. Unfortunately, this does not show in the type system so you have to track that manually / mentally. This already forbids some replacements that might otherwise be worthwile, so it must become 0. in your list of rules. :)

For example, creating a collection of seed elements that are later modified by other code might look like this:

private final Set<String> commonLetters = initialCommonLetters()

private static Set<String> initialCommonLetters() {
    Set<String> letters = new ArrayList<>();
    return letters;

Would be great to simply write commonLetters = Set.of("a", "e"); but this will likely break other code as the returned set is immutable.


The (im)mutability discussion immediately leads to constants. This was a major reason to introduce them! Gone are the days where you need a static initializer block to create that COMMON_LETTERS constant. This would hence be the place where I would look first for use cases.


As you say, there seems to be no reason to start replacing calls to Collections::empty... or Arrays::asList just for the fun of it. What I would do, though, as soon as I start using the new methods in a class I would replace the old variants as well to have the code rely on fewer concepts, making understanding it easier.


The last argument is also one that could apply to the of() variants in general. While Collections::empty... is clearer about its intent, I slightly tend towards saying always using of, no matter how many arguments you have, offsets that advantage by writing code that, as a whole, uses less concepts.

I see no reason to continue using Arrays::asList.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download