Coleções Ordenadas em Java: SortedSet, NavigableSet e TreeSet
SortedSet
A interface SortedSet serve para criar coleções que armazenam elementos de forma ordenada, com ordenação em ordem crescente. Essa interface estende Set, o que significa que a coleção guarda apenas valores únicos. SortedSet oferece métodos como:
E first(): retorna o primeiro elemento do conjunto.E last(): retorna o último elemento do conjunto.SortedSet<E> headSet(E end): retorna um objetoSortedSetcom todos os elementos do conjunto original até o elementoend, sem incluirend.SortedSet<E> subSet(E start, E end): retorna um objetoSortedSetcom todos os elementos do conjunto original entrestarteend, incluindostart, mas sem incluirend.SortedSet<E> tailSet(E start): retorna um objetoSortedSetcom todos os elementos do conjunto original a partir destart, incluindostart.
NavigableSet
A interface NavigableSet estende SortedSet e permite extrair elementos com base em seus valores. NavigableSet define métodos como:
E ceiling(E obj): busca no conjunto o menor elementoeque seja maior ou igual aobj. Caso encontre, retorna esse elemento; caso contrário, retornanull.E floor(E obj): busca no conjunto o maior elementoeque seja menor ou igual aobj. Caso encontre, retorna esse elemento; caso contrário, retornanull.E higher(E obj): busca no conjunto o menor elementoeque seja maior queobj. Caso encontre, retorna esse elemento; caso contrário, retornanull.E lower(E obj): busca no conjunto o maior elementoeque seja menor queobj. Caso encontre, retorna esse elemento; caso contrário, retornanull.E pollFirst(): retorna o primeiro elemento e o remove do conjunto.E pollLast(): retorna o último elemento e o remove do conjunto.NavigableSet<E> descendingSet(): retorna um objetoNavigableSetcom todos os elementos do conjunto original em ordem reversa.NavigableSet<E> headSet(E upperBound, boolean incl): retorna um objetoNavigableSetcom todos os elementos do conjunto original atéupperBound. O parâmetroincl, quandotrue, incluiupperBoundno resultado.NavigableSet<E> tailSet(E lowerBound, boolean incl): retorna um objetoNavigableSetcom todos os elementos do conjunto original a partir delowerBound. O parâmetroincl, quandotrue, incluilowerBoundno resultado.NavigableSet<E> subSet(E lowerBound, boolean lowerIncl, E upperBound, boolean highIncl): retorna um objetoNavigableSetcom todos os elementos do conjunto original delowerBoundatéupperBound, com inclusão definida pelos parâmetroslowerInclehighIncl.
TreeSet
A classe genérica TreeSet<E> representa uma estrutura de dados em forma de árvore, na qual todos os objetos ficam armazenados de forma ordenada em ordem crescente. TreeSet herda de AbstractSet e implementa NavigableSet, o que inclui também SortedSet.
TreeSet possui construtores como:
TreeSet(): cria uma árvore vazia.TreeSet(Collection<? extends E> col): cria uma árvore e adiciona todos os elementos da coleçãocol.TreeSet(SortedSet<E> set): cria uma árvore e adiciona todos os elementos do conjunto ordenadoset.TreeSet(Comparator<? super E> comparator): cria uma árvore vazia, na qual os elementos adicionados serão ordenados pelo comparador.
TreeSet suporta métodos padrão para inserção e remoção de elementos. No exemplo a seguir, uma TreeSet de strings é criada e elementos são adicionados. Em seguida, o tamanho é exibido, um elemento é removido e os restantes são impressos em um loop for-each. Como os elementos se ordenam automaticamente ao serem inseridos, a saída aparece em ordem crescente.
import java.util.TreeSet;
public class Program{
public static void main(String[] args) {
TreeSet<String> states = new TreeSet<String>();
// adicionamos na lista alguns elementos
states.add("Germany");
states.add("France");
states.add("Italy");
states.add("Great Britain");
System.out.printf("TreeSet contains %d elements \n", states.size());
// remoção de elemento
states.remove("Germany");
for(String state : states){
System.out.println(state);
}
}
}A saída mostra o conjunto ordenado:
TreeSet contains 4 elements France Great Britain Italy
Como TreeSet implementa NavigableSet e, por extensão, SortedSet, métodos dessas interfaces podem ser aplicados. No exemplo abaixo, elementos são adicionados a uma TreeSet e métodos como first, last, subSet, higher, lower, descendingSet, headSet e tailSet são chamados para manipular e exibir subconjuntos ou elementos específicos. Isso demonstra como a estrutura permite acessar partes ordenadas do conjunto de maneira simples.
import java.util.*;
public class Program{
public static void main(String[] args) {
TreeSet<String> states = new TreeSet<String>();
// adicionamos na lista alguns elementos
states.add("Germany");
states.add("France");
states.add("Italy");
states.add("Spain");
states.add("Great Britain");
System.out.println(states.first()); // obtemos o primeiro elemento, o menor
System.out.println(states.last()); // obtemos o último elemento, o maior
// obtemos um subconjunto de um elemento até outro
SortedSet<String> set = states.subSet("Germany", "Italy");
System.out.println(set);
// elemento do conjunto maior que o atual
String greater = states.higher("Germany");
// elemento do conjunto menor que o atual
String lower = states.lower("Germany");
// retornamos o conjunto em ordem reversa
NavigableSet<String> navSet = states.descendingSet();
// retornamos o conjunto com todos os elementos menores que o atual
SortedSet<String> setLower=states.headSet("Germany");
// retornamos o conjunto com todos os elementos maiores que o atual
SortedSet<String> setGreater=states.tailSet("Germany");
System.out.println(navSet);
System.out.println(setLower);
System.out.println(setGreater);
}
}Resumo
SortedSet: Interface para coleções ordenadas em ordem crescente, com elementos únicos e métodos para acessar partes do conjunto.NavigableSet: Extensão deSortedSetque permite buscas baseadas em valores, como ceiling, floor e subconjuntos inclusivos.TreeSet: Classe que implementaNavigableSetem estrutura de árvore, com ordenação automática e construtores para inicialização variada.
📝 Exercícios
Tarefa 1
Descrição: Considere o seguinte TreeSet de números, que já está em ordem: {10, 20, 40, 50}. Qual das chamadas de método abaixo retornaria o valor 20?
// Suponha que este TreeSet já existe:
TreeSet<Integer> numeros = new TreeSet<>(Arrays.asList(10, 20, 40, 50));Alternativas:
numeros.higher(20)numeros.ceiling(25)numeros.floor(25)numeros.lower(10)
Resposta
numeros.floor(25)
{10, 20, 40, 50}:
higher(20): Retorna o menor elemento que é estritamente maior que 20. O resultado seria 40.ceiling(25): Retorna o menor elemento que é maior ou igual a 25. O resultado seria 40.floor(25): Retorna o maior elemento que é menor ou igual a 25. O resultado seria 20.lower(10): Retorna o maior elemento que é estritamente menor que 10. Não existe tal elemento no conjunto, então o resultado seria null.Tarefa 2
Descrição: Você tem um TreeSet de notas de exames. Use os métodos de NavigableSet para encontrar e imprimir:
- A maior nota que ainda é considerada "reprovada" (qualquer nota estritamente abaixo de 60).
- A menor nota que já é considerada "excelente" (qualquer nota maior ou igual a 90).
Código inicial:
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
TreeSet<Integer> notas = new TreeSet<>();
notas.add(88);
notas.add(55);
notas.add(92);
notas.add(75);
notas.add(49);
notas.add(98);
notas.add(65);
notas.add(90);
// Encontre a maior nota que é < 60
Integer maiorNotaReprovado = null; // Seu código aqui
// Encontre a menor nota que é >= 90
Integer menorNotaExcelente = null; // Seu código aqui
System.out.println("Maior nota entre os reprovados (< 60): " + maiorNotaReprovado);
System.out.println("Menor nota entre os excelentes (>= 90): " + menorNotaExcelente);
}
}Resposta
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
TreeSet<Integer> notas = new TreeSet<>();
notas.add(88);
notas.add(55);
notas.add(92);
notas.add(75);
notas.add(49);
notas.add(98);
notas.add(65);
notas.add(90);
// O método lower(E e) retorna o maior elemento estritamente menor que 'e'.
Integer maiorNotaReprovado = notas.lower(60);
// O método ceiling(E e) retorna o menor elemento maior ou igual a 'e'.
Integer menorNotaExcelente = notas.ceiling(90);
System.out.println("Maior nota entre os reprovados (< 60): " + maiorNotaReprovado);
System.out.println("Menor nota entre os excelentes (>= 90): " + menorNotaExcelente);
}
}Maior nota entre os reprovados (< 60): 55 Menor nota entre os excelentes (>= 90): 90
notas.lower(60): Procura no conjunto ordenado ({49, 55, 65, 75, 88, 90, 92, 98}) pelo maior elemento que ainda é estritamente menor que 60. Esse valor é 55.notas.ceiling(90): Procura no mesmo conjunto pelo menor elemento que é maior ou igual a 90. Esse valor é 90.
Esses métodos de NavigableSet são extremamente eficientes para realizar esse tipo de busca por proximidade em coleções ordenadas.