5

I need to expose an API - consume(sequence) below - which mandates that its argument sequence collection be ordered as in the below excerpt:

interface Consumer<T> {
    /**
     * @param sequence: an *ordered* collection of Ts to be processed in order
     */
    public void consume(Collection<T> sequence);
}

interface Producer<T> {
    Collection<T> getSequence();
}

class Producer1<T> implements Producer<T> {
    public List<T> getSequence() {
        return new ArrayList<>();
    }
}
class Producer2<T> implements Producer<T> {
    public Deque<T> getSequence() {
        return new LinkedList<>();
    }
}

class Test {
    void testMethod(Consumer<Long> consumer) {
        consumer.consume(new Producer1<Long>().getSequence());
        consumer.consume(new Producer2<Long>().getSequence());
    }
}

Typically one would specify consume() as accepting a List; however, some producers also expose a Deque, so as to facilitate things like efficient reverse-iteration using descendingIterator(). However Deque doesn't extend List and there are likely good reasons for this (O(n) cost of accessing an indexed element in a LinkedList).

So it seems the only way to "keep the compiler happy" is to specify sequence as a Collection; however, according to the Javadoc (and as we all know), a "some are ordered and others unordered", so the consume() API looses in semantics.

Another workaround would be to have Producer2 expose a LinkedList rather than a Deque (and revert consume() to accept a List) but we know it's not ideal to expose implementations rather than interfaces.

It seems the ideal solution would be for Java to provide a Sequence super-interface to List and Deque (extending Iterable). I can imagine one reason this wasn't done is complexity but I think this example demonstrates the need.

Am I missing a better strategy here or do I just need to wait for a revision of the API? For the record, this is Java 17.

3 Answers 3

8

There just happened to be a discussion about this in the OpenJDK mailing list. You can find an archive here: https://mail.openjdk.java.net/pipermail/core-libs-dev/2022-February/085683.html. That discussion mentions the new JEP draft: Sequenced Collections launched this year, 2022-01.

Until that is resolved, I'm afraid you'll have to resort to documenting that the collections need to be ordered, and trusting that callers adhere to your precondition.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the pointers. Great to hear that I'm not the only one missing this feature and that it might get implemented at some point... Amazing it's "only" taken some 15 years for this gap to be recognized.
@sxc731 your “15 years” looks very arbitrary. Either, you assume 24 years (since the introduction of the Collection API) or you assume 8 years (since the introduction of default methods which allow provide this feature later now without breaking compatibility).
@Holdger; I was referring to the introduction of the Deque in JDK 1.6; I suppose a Sequence super-interface to Dequeand List could have been introduced at the same time without too much hassle? Admittedly this would just address my simplistic use-case, not all the goodies from the JEP.
3

JEP 431: Sequenced Collections

As predicted in the Answer by Rob Spoor, Sequenced Collections were delivered in Java 21. See JEP 431 for details.

You wanted a standard interface that would cover both List & Deque as representing a sequence.

Now you have it. In Java 21 and later, SequencedCollection is a super-interface with both List & Deque as sub-interfaces. So concrete classes such as ArrayList, LinkedList, and ArrayDeque can all be referred to as a SequencedCollection.

SequencedCollection<String> x = new ArrayList<>() ;
SequencedCollection<String> y = new LinkedList<>() ;
SequencedCollection<String> z = new ArrayDeque<>() ;

Specific to your Question, you can now declare your consume method as taking a SequencedCollection rather than the more general Collection.

public void consume( SequencedCollection<T> sequence );

Those classes gained new features. All implementations of SequencedCollection offer methods to add, get, and remove elements from the first and last positions. They also offer a reversed method to iterate in opposite order.

For more info, see excellent presentation by Stuart Marks, the lead on JEP 431. Here is his class diagram:

diagram of Java Collection Framework class hierarchy with SequencedCollection added

Comments

1

Sequenced Collections API has already been integrated into JDK codebase and will be released along with JDK 21 on September 19, 2023.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.