Sitemap
MrDebugg3r

MrDebugg3r

Java 21 Sequenced Collections — II

3 min readSep 10, 2024

No artigo anterior, eu inicie o assunto das Sequenced Collections, os problemas das Collections pré-Java 21 e quais soluções vêm no Java 21: os ordinais de posição e a adaptação da hierarquia de classes ao Framework. Para saber mais sobre esse tema, leia o artigo anterior.

Antes de passar ao tema, façamos uma desambiguação. “Sequenced Collections” é um conjunto de classes e interfaces com a característica de usar os ordinais de posição (encounter order). E SequencedCollection é uma interface Java que possui a implementação das “Coleções Sequenciadas”. Portanto, Sequenced Sets e Sequenced Maps também são sequenciadas, mesmo os Maps não fazendo parte da hierarquia com a interface SequencedCollection.

Sequenced Sets

Começando pelos sequenced sets, eles estendem a interface SequencedCollection e não contem elementos duplicados. A interface SequencedSet estende Set que estende Collection.

Relembrando: “coleções sequenciadas” significa que há uma coleção arranjada por primeiro, segundo, até o último elemento e a ideia é manipulá-la pela adição, remoção ou obtenção de valores mais facilmente.

Vamos testar o SequencedSet com uma de suas implementações mais usadas, o LinkedHashSet, que mantém a ordem na qual os elementos são inseridos.

SequencedSet<String> sequencedSet = new LinkedHashSet<>();
sequencedSet.add("Letra B");
sequencedSet.add("Letra Z");
sequencedSet.addFirst("Letra A"); // adiciona ao início do set
// saída: sequencedSet [Letter A, Letter B, Letter Z]

sequencedSet.addFirst("Letra A"); // adição sem efeito, não é possível adicionar elementos duplicados

sequencedSet.addLast("Letra Y"); // adiciona no fim do set

sequencedSet.removeFirst(); // remove o 1°elemento e retorna "Letra A"
sequencedSet.removeLast(); // remove o último elemento e retorna "Letra Z"

sequencedSet.reversed().forEach( System.out::println ); // saída: Letra Z
// Letra B "os elementos estão na ordem inversa"

LinkedHashSet revolve uma deficiência de longa data, a saber, a incapacidade de reposicionar elementos.

Podemos mudar LinkedHashSet para TreeSet, mas nem todos os métodos de SequencedSet irão funcionar. addFirst e addLast lançarão uma UnsupportedOperationException. Então, atenção aqui, pois algumas classes concretas têm um contexto. TreeSet também é uma SortedSet, e esta coleção posiciona elementos por meio de comparação relativa e não suporta operações de posicionamento explícito.

SequencedSet<String> sequencedSet = new TreeSet<>();  // usando TreeSet
sequencedSet.add("Letra B");
sequencedSet.add("Letra Z");
sequencedSet.addFirst("Letra A"); // lança uma UnsupportedOperationException

Sequenced Maps

Get MrDebugg3r’s stories in your inbox

Join Medium for free to get updates from this writer.

Um mapa sequenciado é um Map cujas entradas tem um ordinal de posição (encounter order). Na prática, a interface SequencedMap não estende a interface SequencedCollection, mas ainda assim ela possui/implementa o conceito das coleções sequenciadas, portanto também é uma sequenced collection.

SequencedMap estende a interface Map. Os novos métodos tipo put* têm uma semântica especial. Mapas como LinkedHashMap têm o efeito adicional de reposicionar a entrada se ela já estiver presente no mapa.

Os métodos first/lastEntry, pollFirst/LastEntry foram promovidos da interface NavigableMap.

LetraSequencedMap<String, String> sequencedMap = new LinkedHashMap<>();
sequencedMap.put("B", "Letra B");
sequencedMap.put("C", "Letra C");

sequencedMap.putFirst("A", "Letra A");
sequencedMap.putLast("Z", "Letra Z");

System.out.println( sequencedMap.firstEntry() ); // saída: A=Letra A
System.out.println( sequencedMap.lastEntry() ); // saída: Z=Letra Z

// o mapa está assim {A=Letra A, B=Letra B, C=Letra C, Z=Letra Z}
// veja como é simples percorrer o mapa no sentido inverso
sequencedMap.reversed().forEach((chave, valor) -> System.out.println( chave + " " + valor ));

No caso dos mapas, usamos put em vez de add, putFirst/Last() em vez de addFirst/Last(), e ainda first/lastEntry() em vez de getFirst/Last(), em comparação a SequencedCollection.

// mesmo código anterior aqui
sequencedMap.pollFirstEntry(); // remove a primeira entrada
sequencedMap.pollLastEntry(); // remove a segunda entrada
// {B=Letra B, C=Letra C} <- o mapa está assim agora

Os métodos pollFirst/Last() servem para “consultar” os valores e ao mesmo tempo removê-los do mapa. Observe que no diagrama acima os métodos poll devolvem um Map.Entry<K,V>.

// continuando o código
sequencedMap.sequencedKeySet(); // saída: [B, C]
sequencedMap.sequencedValues(); // saída: [Letra B, Letra C]

Finalmente, veja como os métodos sequencedKeySet() e sequencedValues() devolvem uma coleção de SequencedSet e uma coleção de SequencedCollection respectivamente. Facilitando a obtenção de todas as chaves e valores.

Este artigo lhe foi útil? Deixe o seu “aplauso” e comentário, basta se inscrever com o Google, rápido e simples!

Referências

MARKS, Stuart. JEP 431: Sequenced Collections. 23 out. 2023. Disponível em: https://openjdk.org/jeps/431. Acesso em: 2 setembro 2024.

--

--