Hi Rémi The discussion "new types? or new default methods?" is indeed a valid one. In fact, I think this choice has already been made once in favor of a default method, when adding `List::sort` was chosen over adding `SortedList` (though I imagine that choice was a no-brainer).
In this case I prefer adding new types though, so I wanted to share my take on this. In the following diagram (see [1] in case it got mangled), I've tried to arrange all relevant Collection types by their defining characteristics: |- Collection ---------------------------------------------------------------------------------------------------------------| |unordered ordered sorted distinct distinct & ordered distinct & sorted | | Set | | Queue = (get|remove)First + addLast PriorityQueue | | Stack = (add|get|remove)Last | | Deque = Queue + Stack + addFirst LinkedHashSet SortedSet | | List = Deque + (add|get|remove)Indexed List::sort NavigableSet | |----------------------------------------------------------------------------------------------------------------------------| As I see it, there are a couple of issues with this: * conceptually, every List is a Deque, but List doesn't extend Deque. If it would, all uses of List (e.g. as a parameter type in APIs) where the indexed access isn't required could be replaced with Deque instead. Or e.g. when you need to take a stack as argument: currently Deque is the recommended parameter type, but that means you can't just pass a List to the method as-is. With RC, you'd be able to use that as parameter type and pass both Deque and List. * LinkedHashSet and SortedSet lack a common ancestor which asserts "this is an ordered set". So when defining an API, I'm forced to choose between SortedSet, which is more specific than I want, or List, which is more generic than I want (usually I go with SortedSet, because enforcing something through Javadoc isn't very reliable (cf. Collectors::toList: even though the spec clearly says the result might not be modifiable, people tend to simply assume it is)). Now with RC/RS these issues would be solved, where RC is ~ Deque + reversed, and RS ~ Deque + distinct + reversed. In terms of the diagram, they group together a bunch of closely-related Collection types (see [1] if needed): |- Collection ---------------------------------------------------------------------------------------------------------------| |unordered ordered sorted distinct distinct & ordered distinct & sorted | | Set | | Queue = (get|remove)First + addLast PriorityQueue | | Stack = (add|get|remove)Last | | |- ReversibleCollection -----------------------------------| |- ReversibleSet -----------------------|| | |Deque = Queue + Stack + addFirst | |LinkedHashSet SortedSet || | |List = Deque + (add|get|remove)Indexed List::sort | | NavigableSet || | |----------------------------------------------------------| |---------------------------------------|| |----------------------------------------------------------------------------------------------------------------------------| On Wednesday, May 12, 2021 13:22 CEST, fo...@univ-mlv.fr wrote: > First, i think we have overlooked ReversibleMap, if you have a LinkedHashMap, > the keySet should be a ReversibleSet. I'm not sure what you meant, but the PR already defines `LinkedHashMap::keySet` as `public ReversibleSet<K> keySet()`. > Again, we have seen that introducing those interfaces > - is not source backward compatible thus it will be painful for some of our > users, > I believe NavigableSet/NavigableMap did not have that issue because only > one existing implementation per interface was retrofitted to implement those > interfaces, TreeSet for NavigableSet and TreeMap for NavigableMap. > ConcurrentSkipListSet/ConcurrentSkipListMap were added at the same time, so > there was no existing code doing a lub (lowest upper bound) between TreeSet > and ConcurrentSkipListSet. > Here, they are a lot of implementations that will implement be retrofitted > to ReversibleCollection, ReversibleSet and ReversibleMap. As far as I understand, both options might cause source incompatibilities, but I assume you estimate the actual impact of adding default methods to be (much) smaller? > - people will have to wait a theoretically infinite time before being to > introduce a public method that takes a ReversibleCollection, ReversibleSet > and ReversibleMap to their library, because it requires > all existing implementations of collection with an order to be retrofitted > to implement those interfaces. I think I'm missing something here. I just did an experiment to convince myself that the set of interfaces a class implements isn't hard-wired in its class file. In other words, that any custom List/Deque/SortedSet/... implementation would be seen as implementing RC/RS without having to recompile it (that, or my experiment was flawed somehow, of course). So am I correct that your concerns are only about custom collections that implement Collection directly? If so, if I'd introduce a public method in my library today, I'd have to declare the parameter as Collection in order for custom collections to be able to use it. So in the future, I could either introduce an overloaded the method (one with a Collection parameter & one with a ReversibleCollection), or I could expect clients to do `List::copyOf`... right? I'd appreciate it if you could elaborate on this point, because I don't understand the concern yet. > - adding any new interfaces has a real cognitive cost, the collection API is > supposed to be simple, does being reversible really worth such new weight. I believe this is subjective, but to me the new interfaces are like "the missing piece" of the Collections API puzzle. I believe their value is also in the fact that they reconcile List/Deque and LinkedHashSet/SortedSet and are very useful as parameter/return types in APIs. > > > > s'marks > > Rémi Kind regards, Anthony [1] https://gist.github.com/anthonyvdotbe/e2e313693f032e4336e5385334a476db