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