RFC: draft API for JEP 269 Convenience Collection Factories
stuart.marks at oracle.com
Sat Oct 17 17:56:50 UTC 2015
On 10/14/15 10:56 AM, Kevin Bourrillion wrote:
> (Sorry that Guava questions were asked and I didn't notice this thread sooner.)
Hi Kevin, thanks for this feedback. It's still timely, as it's helping to
improve the proposal.
> Note that we have empirically learned through our Lists/Sets/Maps factory
> classes that varargs factory methods for /mutable/ collections are almost
> entirely useless. For one thing, it's simply not common to have a hardcoded
> set of initial values yet still actually need to modify the contents later.
> When that does come up, the existing workarounds just aren't bad at all: [...]
> Anyway, since we created these methods, they became an attractive nuisance,
> and thousands of users reach for them who would have been better off in every
> way using an immutable collection. Our fondest desire is to one day be able to
> delete them. So, obviously, my strong recommendation is not to add these to
> ArrayList, etc.
This is very, very interesting.
I have to admit that our rationale in proposing to add the factories to the
concrete implementations is fairly weak. It was something along the lines of,
"Well these will /obviously/ be useful, so let's go ahead and add them."
(Perhaps this is similar to the rationale for adding them to Guava in the first
Based on your experience, and feedback from other replies to this email, I'm
strongly leaning toward removing the factories from the concrete collections.
It could be that not having these would be a mistake. But if it is, it's easier
to add them later, than it is to add them now and to try to remove them later if
we determine that they were a mistake. (As Dr Deprecator is all too aware.)
The class static method inheritance issue is an annoyance, but I don't think
it's central to the problem. If we were to add static factories to classes, I'm
confident we'd come up with some way to deal with the issue. What I think /is/
central to the issue is what you described as an "attractive nuisance." If the
presence of these methods is likely to cause them to be misused more often then
not, then that's a good reason not to have the API there at all.
More discussion below...
> On Fri, Oct 9, 2015 at 4:11 PM, Stuart Marks <stuart.marks at oracle.com
> <mailto:stuart.marks at oracle.com>> wrote:
> Now, Guava handles this use case by providing a family of copying
> factories that can accept an array, a Collection, an Iterator, or an
> Iterable. These are all useful, but for JEP 269, we wanted to focus on the
> "collection literal like" APIs and not expand the proposal to include a
> bunch of additional factory methods. Since we need to have a varargs
> method anyway, it seemed reasonable to arrange it so that it could easily
> accept an array as well.
> A decision to support only varargs and arrays is reasonable. However, I don't
> see the advantage in using the same method name for both. In Guava, it's clear
> what the difference between ImmutableList.of(aStringArray) and
> ImmutableList.copyOf(aStringArray) is.
There's a small, but not fundamental, advantage to having the same name.
Suppose we have fixed-arg variants up to 5 and a one-arg varargs method:
List.of(T, T, T, T, T)
Then it becomes possible to write,
List<String> list = List.of("a", "b", "c", "d", "e");
and later modify it to
List<String> list = List.of("a", "b", "c", "d", "e", "f");
without having to worry about renaming the method call. Of course, we could
solve this by changing the varargs variant so that the varargs parameter occurs
after all the fixed parameters, like Guava:
List.of(T, T, T, T, T, T, T...)
But then we'd need to add another method to handle the array case:
It's not a huge deal to add another method, I suppose. The only disadvantage I'm
aware with List.of(T...) is that it makes it harder to have a list of an array.
Are there other disadvantages?
> 3. Duplicate handling.
> My current thinking is for the Set and Map factories to throw
> IllegalArgumentException if a duplicate element or key is detected.
> To the other question: the reason we chose 11 as the cutoff is that we
> determined that there would be no logical basis for exactly where to do it, so
> we looked for an illogical basis. Sometimes you'll be at 10, all the way up,
> you're at 10 and where can you go from there? Where? Nowhere. So this way, if
> we need that extra push over the cliff, we can go up to 11.
It seems there are only two interesting numbers in software development, 11 and
42. In this case 42 is right out, so that leaves 11.
More information about the core-libs-dev