ReversibleCollection proposal
Stuart Marks
stuart.marks at oracle.com
Mon Apr 19 15:41:11 UTC 2021
On 4/17/21 9:49 AM, Remi Forax wrote:
> I think the analysis is spot on but I don't think the proposed solution is the right one.
>
> Introducing a new interface (two in this case) has a really huge cost and in this case, i've trouble to see why i will want to write a method that takes a ReversibleCollection as parameter, ReversibleCollection as a type does not seem to be useful. About the cost of introducing a new collection interface, it means that we also have to update all emptyXXX, singleXXX, uncheckedXXX with a new interface, and that only for the JDK. Every libraries that proxy collections has also to be updated to take care of this new type, otherwise the integration with an application that uses this new type and the library is not seamless anymore.
Hi Remi,
Thanks for looking at this. There are several issues intertwined here, so let's try
to break it down.
There are a bunch of factory methods emptyX, singletonX, etc. that give instances of
particular types. As Tagir noted, List is a ReversibleCollection, so you can just
use emptyList or List.of or whatever if you need an instance of
ReversibleCollection. Also, SortedSet/NavigableSet are ReversibleSets, so if you
need an empty ReversibleSet, you can use Collections.emptyNavigableSet. There's no
singletonNavigableSet, but you could do
Collections.unmodifiableNavigableSet(new TreeSet<>(List.of(x)))
which is a bit of a mouthful, but it's possible. (The fact that there's no
Collections.singletonNavigableSet may mean this use case is so narrow that few
people really needed it.)
As for the wrappers, synchronizedX and checkedX are mostly disused, so I don't see a
need to provide those wrappers. Having unmodifiable RC and RS is probably useful, so
I could see adding those. That's a certain amount of work, but not a tremendous cost.
> All these methods can be introduced has default methods on the existing collection interfaces, there is no need of a special interface (or two) for that.
Clearly it's possible to get by without new interfaces. After all the collections
framework has gotten by without them for 20+ years already. It's certainly possible
to fill out the individual interfaces (List, Deque, Sorted/NavSet) and classes
(LinkedHashSet, LinkedHashMap) with methods that are all similar to each other, and
that would be useful. Or as Peter Levart pointed out, we could push all of them up
to Collection and write the specs in a loose enough way to encompass even unordered
collections.
Any of those alternatives (do nothing, add individual methods, add loosely-spec'd
methods to Collection) are *possible* to do. However, I think you know how minimal
we are with the JDK APIs, and we wouldn't have proposed new interfaces without good
cause. Thus, I think introducing new *types* here is useful, for the following reasons.
* There's a useful clump of semantics here, combined with sensible operations that
rely on those semantics. There are a lot of places in the spec where there is
hedging of the form "if the collection has an ordering, then... otherwise the
results are undefined". This is unnecessary in the context of a new type.
Furthermore, the new operations fit well with the new types' semantics, with no
hedging necessary.
* These semantics appear across a broad range of existing collection types and
implementations. It's quite valuable to have a type that unifies the common pieces
of List, Deque, SortedSet, and LinkedHashSet into a single abstraction.
* It's useful to have a new type for parameters in APIs. There are times when one
wants to accept something like a List -or- a LinkedHashSet. Typically one would
accept a Collection and then write a spec with hedging as above ("the argument
collection must have a defined ordering"). But this also allows bugs, for example if
somebody accidentally passes a HashSet. Having ReversibleCollection helps this problem.
* It's useful to have a new type for return types in APIs. Consider
LinkedHashMap's entrySet, keySet, and values views. While we clearly get by with
having these return Set or Collection today, we need a place to put the new methods.
Either they go on Collection (and have extremely weak semantics) or we define new
interfaces.
* It's a useful interface for new collection implementations. There are data
structures that are ordered, double-ended, and reversible, but for which
implementing List is too onerous. Supporting int indexes in various List APIs is
where stumbling blocks usually occur. I note that the LinkedHashMap view collections
are examples of this that already exist in the prototype code. (Other possibilities
might be something like SpinedBuffer or chunked linked lists.)
In general, I agree that there should be strict criteria for introducing new
interfaces into collections, but I think this proposal meets them.
s'marks
More information about the core-libs-dev
mailing list