Feature Java: Sequenced Collections
O Java 21 lançou a feature Sequenced Collections para simplificar ainda mais o uso de coleções. Esse aprimoramento da linguagem auxilia o desenvolvedor no momento em que é necessário realizar alguma operação nos primeiros ou últimos registros de uma coleção.
Este post visa explorar a nova funcionalidade, demonstrando sua aplicação em diversos tipos de coleções por meio de exemplos.
Sequenced Collections Interfaces
Essa nova funcionalidade introduziu três novas interfaces:
SequencedCollection
A interface SequencedCollection estende Collection e declara os seguintes métodos:
- 
SequencedCollection<E> reversed(): Retorna uma visão ordenada inversa da coleção.
 - 
void addFirst(E e): Adiciona um elemento como o primeiro elemento da coleção.
 - 
void addLast(E e): Adiciona um elemento como o último elemento da coleção.
 - 
E getFirst(): Retorna o primeiro elemento da coleção.
 - 
E getLast(): Retorna o último elemento da coleção.
 - 
E removeFirst(): Remove e retorna o primeiro elemento da coleção.
 - 
E removeLast(): Remove e retorna o último elemento da coleção.
 
SequencedSet
Já a interface SequencedSet estende SequencedCollection declara apenas um único método:
- 
SequencedSet<E> reversed(): Retorna uma visão ordenada inversa da coleção.
 
SequencedMap
A interface SequencedMap estende Map e declara os seguintes métodos:
- 
SequencedMap<K, V> reversed(): Retorna uma visão ordenada inversa do mapa.
 - 
Map.Entry<K,V> firstEntry(): Retorna o primeiro mapeamento do mapa.
 - 
Map.Entry<K,V> lastEntry(): Retorna o último mapeamento do mapa.
 - 
Map.Entry<K,V> pollFirstEntry(): Remove e retorna o primeiro mapeamento do mapa.
 - 
Map.Entry<K,V> pollLastEntry(): Remove e retorna o último mapeamento do mapa.
 - 
V putFirst(K k, V v): Insere como o primeiro registro do mapa se ainda não estiver presente.
 - 
V putLast(K k, V v): Insere como o último registro do mapa se ainda não estiver presente.
 - 
SequencedSet<K> sequencedKeySet(): Retorna um SequencedSet contendo as chaves do mapa.
 - 
SequencedCollection<V> sequencedValues(): Retorna uma SequencedCollection contendo os valores do mapa.
 - 
SequencedSet<Map.Entry<K, V>>: Retorna um SequencedSet contendo o mapeamento do mapa.
 
Exemplos
Neste primeiro exemplo utilizaremos os métodos providos pela interface SequencedCollection.
public static void main(String[] args) {
    var nomes = new ArrayList<String>();
    nomes.add("Gaspar");
    nomes.add("Laura");
    System.out.println(nomes.getFirst()); // Gaspar
    nomes.addFirst("Cecilia");
    nomes.addLast("Murilo");
    System.out.println(nomes.getFirst()); // Cecilia
    System.out.println(nomes.getLast()); // Murilo
    var nomesReverso = nomes.reversed();
    System.out.println(nomesReverso.getFirst()); // Murilo
    System.out.println(nomesReverso.getLast()); // Cecilia
    System.out.println(nomesReverso.removeFirst()); // Murilo
    System.out.println(nomesReverso.removeFirst()); // Laura
    System.out.println(nomesReverso.removeLast()); // Cecilia
}
Exemplo de utilização do SequencedSet num conjunto de frutas, acessando todos os métodos disponibilizados pela interface.
public static void main(String[] args) {
    var frutas = new LinkedHashSet<>();
    frutas.add("Banana");
    frutas.add("Maça");
    System.out.println(frutas.getFirst()); // Banana
    frutas.addFirst("Abacate");
    frutas.addLast("Melancia");
    System.out.println(frutas.getFirst()); // Abacate
    System.out.println(frutas.getLast()); // Melancia
    var frutasReverso = frutas.reversed();
    System.out.println(frutasReverso.getFirst()); // Melancia
    System.out.println(frutasReverso.getLast()); // Abacate
    System.out.println(frutasReverso.removeFirst()); // Melancia
    System.out.println(frutasReverso.removeFirst()); // Maça
    System.out.println(frutasReverso.removeLast()); // Abacate
}
Em nosso último exemplo, utilizaremos todos os novos métodos providos pela interface SequencedMap.
public static void main(String[] args) {
    var mapa = new LinkedHashMap<String, String>();
    mapa.put("chave-gaspar", "Gaspar Barancelli");
    mapa.put("chave-laura", "Laura Barancelli");
    System.out.println(mapa.firstEntry().getValue()); // Gaspar Barancelli
    mapa.putFirst("chave-cecilia", "Cecilia Barancelli");
    mapa.putLast("chave-murilo", "Murilo Barancelli");
    System.out.println(mapa.firstEntry().getValue()); // Cecilia Barancelli
    System.out.println(mapa.lastEntry().getValue()); // Murilo Barancelli
    var values = mapa.sequencedValues();
    System.out.println(values.getFirst()); // Cecilia Barancelli
    System.out.println(values.getLast()); // Murilo Barancelli
    var chaves = mapa.sequencedKeySet();
    System.out.println(chaves.getFirst()); // chave-cecilia
    System.out.println(chaves.getLast()); // chave-murilo
    var mapeamento = mapa.sequencedEntrySet();
    System.out.println(mapeamento.getFirst().getValue()); // Cecilia Barancelli
    System.out.println(mapeamento.getLast().getValue()); // Murilo Barancelli
    var mapaReverso = mapa.reversed();
    System.out.println(mapaReverso.firstEntry().getValue()); // Murilo Barancelli
    System.out.println(mapaReverso.lastEntry().getValue()); // Cecilia Barancelli
    System.out.println(mapaReverso.pollFirstEntry().getValue()); // Murilo Barancelli
    System.out.println(mapaReverso.pollFirstEntry().getValue()); // Laura Barancelli
    System.out.println(mapaReverso.pollLastEntry().getValue()); // Cecilia Barancelli
}
Conclusão
As Sequenced Collections do Java 21 representam um salto significativo na forma como gerenciamos coleções, especialmente quando o foco está nos primeiros ou últimos elementos. As novas interfaces e métodos introduzidos facilitam o acesso, a manipulação e a visualização de dados de maneira intuitiva e eficiente.