I'm certain that uses of RC/RS will be rare in the beginning, because they will
be
new, and people won't be familar with them. And then there will the people who
say
"I can't use them because I'm stuck on JDK 11 / 8 / 7 / 6 ...." It was the same
thing with lambdas and streams in Java 8, with List.of() etc in Java 9, records
in
Java 16, etc. This wasn't an argument not to add them, and it isn't an argument
not
to add RC/RS.

All the changes you are listing here are "client side" changes, the ones that 
can be adopted quickly because they do not require to change the API side of any 
libraries.
ReversibleCollection is an API side change, like generics is, those changes 
have a far higher cost because you have to wait your library dependencies to be 
updated.
On the Valhalla list, we have discussed several times about how to alleviate 
those API side change cost using automatic bridging or methods forwarding, even 
for Valhalla, we are currently moving in a state where those mechanisms are not 
needed.

This isn't an argument against RC/RS. Application code can find uses for the new APIs, e.g. getFirst and addLast on List, or more ordering flexibility on LinkedHashSet, on day one. Applications' internal APIs can also benefit on day one. Certainly libraries will have to wait for their clients to catch up to later JDKs. This has *always* been the case, even for library internals (such as use of lambdas or APIs introduced in newer JDKs) because libraries need to be compiled for the lowest version of the JDK their clients support. For example, you can't use List.of() in a library -- even internally -- if your clients are still on JDK 8. There are no new issues here.

The abstraction already exists but it's not defined in term of interface 
because it's an implementation decision and those are cleanly separated in the 
current Collection design.

Let take a step back, the collection API defines basic data structure 
operations in term of interfaces like List, Deque, Set, etc those interfaces 
are decoupled from implementation capabilities like mutable, nullable, ordered 
and checked.

Depending on the implementation capabilities, the interfaces method 
implementation may throw an exception, non-mutable implementations use 
UnsupportedOperationException, non-nullable implementations use NPE and checked 
implementations use CCE.

So what is missing is methods on Collection interfaces that require the 
collection implementation to be ordered like descendingList(), getFirst(), etc.
Those methods that may throw a specific exception if the implementation is not 
ordered, not UnsupportedOperationException but a new one like 
NotOrderedException.

So to answer to your question about LinkedHashSet, the reverse-ordered 
LinkedHashSet is a Set with a method descendingSet() that do not throw 
NotOrderedException like any Set with an order.

To summarize, if we introduce ReversibleCollection, we should also introduce 
ImmutableCollection, NonNullableCollection and CheckedCollection.
I think it's better to consider the fact that being ordered as a capability 
(hint: this is already what the Spliterator API does) and not as a specific 
interface.

This discussion, and your ensuing proposal to add a bunch of throwing default methods to Collection, is based on a flawed premise. That premise is that there is a fundamental distinction between "data structure operations" which must be embodied as types, and "implementation capabilities" which must manifest at runtime either by allowing the operation or by throwing an exception.

But this distinction isn't fundamental. In what way is being ordered not a "basic data structure" issue? In what way is indexed access (as for List) not an "implementation capability"? Really, these are two different aspects of the same thing. Over time, new "data structure operations" and new "implementation capabilities" have been added to the collections framework. Some of them were embodied as types, and some were not. Which ones were embodied as types was the result of design decisions that considered a bunch of tradeoffs.

What you're attempting to do is to declare absolutes. This drives you to one of two extremes, which is either 1) to never add new types and to always add possibly-throwing operations to existing types (which seems to be what you're describing as an alternative); or 2) to claim that everything needs to be manifested as a new type (giving rise to your straw-man argument that we should also have ImmutableCollection, NonNullableCollection, CheckedCollection, etc.). The argument seems to be that we wouldn't want to add all those other types, so we mustn't add ReversibleCollection either. No.

In summary, I reject the premise that adding ReversibleCollection implies that a bunch of other types also need to be added, so I don't accept this line of reasoning as an argument against ReversibleCollection.

s'marks

Reply via email to