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

Reply via email to