Hi Stuart,
Since those factory methods construct general purpose immutable
collections, I miss methods that act as copy constructors (general
purpose collection implementations should have them, says recommendation):
public static <E> List<E> copyOf(Collection<? extends E> collection);
public static <E> Set<E> copyOf(Collection<? extends E> collection);
public static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map);
Sometimes it would be useful also to trust the copy to contain elements
of the specified type (since those are immutable collections, Class
arguments are needed only at construction time to do the check while
constructing):
public static <E> List<E> copyOf(Collection<? extends E> collection,
Class<E> elementType);
public static <E> Set<E> copyOf(Collection<? extends E> collection,
Class<E> elementType);
public static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map,
Class<K> keyType, Class<V> valueType);
As an optimization, those copyOf methods could be specified to return
the passed-in collection if it was already of the correct "immutable" type:
List<String> strings = List.of("a", "b", "c");
assert List.copyOf(strings) == strings;
assert List.copyOf(strings, String.class) == strings; // just checks the
elements
This is different from Collections.immutableXXX(xxx) since the later can
not be used to make "defensive" copies. For example:
class SomeBean {
Set<Option> options = Set.of();
Set<Option> getOptions() {
return options;
}
void setOptions(Set<Option> options) {
this.options = Set.copyOf(options, Option.class);
}
}
Or would that be beyond the scope of this JEP?
Regards, Peter
On 11/24/2015 07:26 AM, Stuart Marks wrote:
Hi all,
Please review these API and implementation changes that comprise the
first integration of JEP 269. I intend to push this under the "initial
API and skeleton implementation" subtask, JDK-8139232.
Changes since the previous review:
- more precise wording regarding static factory methods (thanks Remi)
- add defensive copy and test for List.of(E...) (thanks Michael Hixson)
- more null checking and tests
- various small wording cleanups
- @since 9
I've left the fixed-arg overloads at ten for all three interfaces. The
fixed-arg methods provide a useful fast path for initialization and
non-desktop, non-server cases. The cost is some API clutter; ten
elements or pairs is rather a lot. This number should be sufficient,
though, to handle the vast majority of cases without having to switch
to varargs. Note that the clutter is only in the API definitions, and
it doesn't intrude into the point of call (at least for List and Set).
For the Map case, it's particularly useful to have lots of fixed-arg
overloads, since the varargs case requires switching APIs and adding
more boilerplate.
I've also updated the JEP text to reflect the current proposal, mainly
the removal of the static factory methods from the concrete classes.
JEP:
http://openjdk.java.net/jeps/269
API spec (basically List, Map, and Set):
http://cr.openjdk.java.net/~smarks/reviews/jep269/api.20151123/
Specdiff:
http://cr.openjdk.java.net/~smarks/reviews/jep269/specdiff.20151123/overview-summary.html
Webrev:
http://cr.openjdk.java.net/~smarks/reviews/jep269/webrev.20151123/
Thanks,
s'marks