A word for Remi's concern...

While it is good that List (and SortedSet and Deque) extend ReversibleCollection in the proposal, it is a pity the same is not true for Set and Queue. If Set and Queue could also be ReversibleCollection(s), then we would not need ReversibleCollection at all and the methods could be added to Collection itself.


So let's see them:

public interface Collection<E> .... {
        default Collection<E> reversed() { return this; }
        default void addFirst(E e) { throw new UnsupportedOperationException(); }         default void addLast(E e) { throw new UnsupportedOperationException(); }
        default E getFirst() { return iterator().next(); }
        default E getLast() { return iterator().next(); }
        default E removeFirst() { var i = iterator(); i.next(); i.remove(); }         default E removeLast() { var i = iterator(); i.next(); i.remove(); }
}


List, SortedSet and Deque would of course override them with implementations as proposed. Would anything be wrong with above implementations?

Collection is an Iterable which allows to iterate over elements. We can still iterate a Collection that does not define the order of iteration. We can not rely on such undefined order in our code, but we can still iterate it. Stream.findFirst() is equivalent to Stream.findAny() for unordered streams. So why would Collection.getFirst() and Collection.getLast() not be equivalent (to Collection.getAny()) for unordered Collections? Why would coll.reversed() be any different than coll for unordered collections?

Peter



On 4/18/21 3:53 AM, Tagir Valeev wrote:
Hello, Remi!

On Sat, Apr 17, 2021 at 11:50 PM Remi Forax <fo...@univ-mlv.fr> wrote:
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.
Note that in Stuart's proposal, java.util.List extends
ReversibleCollection. So, existing emptyList() and singletonList()
also return ReversibleCollection and no new methods are necessary
here. Probably unmodifiableReversibleSet could be useful as a
LinkedHashSet wrapper. On the other hand, we don't have, e.g.
checkedDeque or synchronizedDeque, and it looks like nobody complains.
So probably it's not always necessary to create a wrapper for every
single collection interface.

I fully agree that having a way to reverse a collection is a powerful API 
point, as Brian said, it's better to reverse the collection and then ask for a 
stream than providing a method reverseStream (and this is true for iterators or 
views like keySet/entrySet/values or subList too). Several people also ask to 
have findLast() on Stream, using list.descendingList().findFirst() will be 
equivalent.
A dedicated findLast() would be a great addition to reversible
streams! It could short-circuit for reversible stream
(reverse().findFirst()) and use reduce((a, b) -> b) for non-reversible
(so intermediate buffering is not necessary). I've found 8 Stream API
call chains ending with .reduce((a, b) -> b) in our sources. Clearly,
some of them could short-circuit, as the source is potentially
reversible (e.g. allAnchors.subList(0,
idx).stream().filter(hasNewName).reduce((x1, x2) -> x2)). Having
dedicated findLast operation would be less error-prone, compared to
creating the stream as reversed().stream(), as you don't have to think
whether the stream is reversible or not. If you accidentally add a
non-reversible operation, you'll miss the optimization but not
correctness.

With best regards,
Tagir Valeev.

Reply via email to