Java : Sequenced collections

Java21 introduced Sequenced collections to improve the collections framework usability. Until Java21, the general way to get the first and last element of a list looks like the following

list.get(0)
list.get(list.size() - 1)

definitely not great looking code, for LinkedHashSet it’s even worse.

linkedHashSet.iterator().next()

Though many collections types are ordered (List, SortedSet and LinkedHashSet), there was no unifying way in collection framework to represent this ordered-ness (sequence) of the elements. Java21 introduced SequencedCollection interface that works to unify the operations on collections that store elements in deterministic order. With Sequenced collections we can get first and last elements as follows

list.getFirst()
list.getLast()
new interfaces in collection framework
Java Sequenced collection

Sequenced Collection

As we can see from the collection class hierarchy, the new SequencedCollection interface is implemented by List,Deque and SequencedSet. SequencedCollection has the following methods.

SequencedCollection<E> reversed();
void addFirst(E e)
void addLast(E e)
E getFirst();
E getLast();
E removeFirst();
E removeLast();

Full interface of the SequencedCollection is listed below.

public interface SequencedCollection<E> extends Collection<E> {
    /**
     * Returns a reverse-ordered view of this collection.
     */
    SequencedCollection<E> reversed();

    /**
     * Adds an element as the first element of this collection (optional operation).
     */
    void addFirst(E e);

    /**
     * Adds an element as the last element of this collection (optional operation).
     */
    void addLast(E e);

    /**
     * Gets the first element of this collection.
     */
    E getFirst();

    /**
     * Gets the last element of this collection.
     */
    E getLast();

    /**
     * Removes and returns the first element of this collection (optional operation).
     */
     E removeFirst();

    /**
     * Removes and returns the last element of this collection (optional operation).
     */
    E removeLast();
}


public interface SequencedSet<E> extends SequencedCollection<E>, Set<E> {
    SequencedSet<E> reversed();
}

As we can see some methods are optional, for example SortedSet order depends on the element sort order and can’t support adding elements at specific position. The SequencedSet just adds the covariant override for the reversed method.

Though the SequencedCollection unified the operations, performance of each operation might not be same across implementations. For example addFirst expensive on ArrayList but relatively cheap on LinkedList.

Sequenced Map

Maps with well defined mappings order implement SequencedMap interface. The interface is similar to SequencedCollection with additional methods specific to map types. Both SortedMap and LinkedHashMap implement the new SequencedMap interface.

SequencedMap

SequencedMap added several methods that makes it easy to operate on ordered maps. Following methods are available in this new interface.

SequencedMap<K, V> reversed();
Map.Entry<K,V> firstEntry();
Map.Entry<K,V> lastEntry();
Map.Entry<K,V> pollFirstEntry();
Map.Entry<K,V> pollLastEntry();
V putFirst(K k, V v);
V putLast(K k, V v);
SequencedSet<K> sequencedKeySet();
SequencedCollection<V> sequencedValues();
SequencedSet<Map.Entry<K, V>> sequencedEntrySet();

Full interface of SequencedMap is listed below.

public interface SequencedMap<K, V> extends Map<K, V> {
    /**
     * Returns a reverse-ordered <a href="Collection.html#view">view</a> of this map.
     */
    SequencedMap<K, V> reversed();

    /**
     * Returns the first key-value mapping in this map,
     * or null if the map is empty.
     */
    Map.Entry<K,V> firstEntry();

    /**
     * Returns the last key-value mapping in this map,
     * or null if the map is empty.
     */
    Map.Entry<K,V> lastEntry();

    /**
     * Removes and returns the first key-value mapping in this map,
     * or null if the map is empty (optional operation).
     */
    Map.Entry<K,V> pollFirstEntry();

    /**
     * Removes and returns the last key-value mapping in this map,
     * or null if the map is empty (optional operation).
     */
    Map.Entry<K,V> pollLastEntry();

    /**
     * Inserts the given mapping into the map if it is not already present, or replaces the
     * value of a mapping if it is already present (optional operation).
     */
     V putFirst(K k, V v);

    /**
     * Inserts the given mapping into the map if it is not already present, or replaces the
     * value of a mapping if it is already present (optional operation).
     */
    V putLast(K k, V v);

    /**
     * Returns a SequencedSet view of this map's keySet.
     */
    SequencedSet<K> sequencedKeySet();

    /**
     * Returns SequencedCollection view of this map's values collection.
     */
    SequencedCollection<V> sequencedValues();

    /**
     * Returns a SequencedSet view of this map's entrySet.
     */
    SequencedSet<Map.Entry<K, V>> sequencedEntrySet();
}

The sequenced* methods return view of the underlying collections and doesn’t support add & addAll methods.

Similar to SortedSet, SortedMap doesn’t support methods that require explicit placement of the entries (putLast and putFirst)

Tags:,

Add a Comment

Your email address will not be published. Required fields are marked *