Interfaces SortedMap e NavigableMap. Classe TreeMap em Java
Para criar mapeamentos ordenados, o Java oferece interfaces adicionais como SortedMap
e NavigableMap
.
SortedMap
A interface SortedMap<K, V>
estende Map<K, V>
e cria um mapeamento em que todos os elementos ficam ordenados em ordem crescente de suas chaves. SortedMap
adiciona métodos como:
K firstKey()
: retorna a chave do primeiro elemento do mapeamento.K lastKey()
: retorna a chave do último elemento do mapeamento.SortedMap<K, V> headMap(K end)
: retorna um objetoSortedMap
com todos os elementos do mapeamento original até a chaveend
, sem incluirend
.SortedMap<K, V> tailMap(K start)
: retorna um objetoSortedMap
com todos os elementos do mapeamento original a partir da chavestart
, incluindostart
.SortedMap<K, V> subMap(K start, K end)
: retorna um objetoSortedMap
com todos os elementos do mapeamento original destart
atéend
, incluindostart
, mas sem incluirend
.
NavigableMap
A interface NavigableMap<K, V>
estende SortedMap<K, V>
e permite obter elementos do mapeamento em relação a outros elementos. Seus principais métodos incluem:
Map.Entry<K, V> ceilingEntry(K key)
: retorna o elemento com a menor chavek
maior ou igual akey
(k >= key
). Caso não exista, retornanull
.Map.Entry<K, V> floorEntry(K key)
: retorna o elemento com a maior chavek
menor ou igual akey
(k <= key
). Caso não exista, retornanull
.Map.Entry<K, V> higherEntry(K key)
: retorna o elemento com a menor chavek
maior quekey
(k > key
). Caso não exista, retornanull
.Map.Entry<K, V> lowerEntry(K key)
: retorna o elemento com a maior chavek
menor quekey
(k < key
). Caso não exista, retornanull
.Map.Entry<K, V> firstEntry()
: retorna o primeiro elemento do mapeamento.Map.Entry<K, V> lastEntry()
: retorna o último elemento do mapeamento.Map.Entry<K, V> pollFirstEntry()
: retorna e remove o primeiro elemento do mapeamento.Map.Entry<K, V> pollLastEntry()
: retorna e remove o último elemento do mapeamento.K ceilingKey(K key)
: retorna a menor chavek
maior ou igual akey
(k >= key
). Caso não exista, retornanull
.K floorKey(K key)
: retorna a maior chavek
menor ou igual akey
(k <= key
). Caso não exista, retornanull
.K lowerKey(K key)
: retorna a maior chavek
menor quekey
(k < key
). Caso não exista, retornanull
.K higherKey(K key)
: retorna a menor chavek
maior quekey
(k > key
). Caso não exista, retornanull
.NavigableSet<K> descendingKeySet()
: retorna um objetoNavigableSet
com todas as chaves do mapeamento em ordem reversa.NavigableMap<K, V> descendingMap()
: retorna um objetoNavigableMap
com todos os elementos em ordem reversa.NavigableSet<K> navigableKeySet()
: retorna um objetoNavigableSet
com todas as chaves do mapeamento.NavigableMap<K, V> headMap(K upperBound, boolean incl)
: retorna um objetoNavigableMap
com todos os elementos do mapeamento original atéupperBound
. O parâmetroincl
, quandotrue
, incluiupperBound
.NavigableMap<K, V> tailMap(K lowerBound, boolean incl)
: retorna um objetoNavigableMap
com todos os elementos do mapeamento original a partir delowerBound
. O parâmetroincl
, quandotrue
, incluilowerBound
.NavigableMap<K, V> subMap(K lowerBound, boolean lowIncl, K upperBound, boolean highIncl)
: retorna um objetoNavigableMap
com todos os elementos do mapeamento original delowerBound
atéupperBound
. Os parâmetroslowIncl
ehighIncl
, quandotrue
, incluemlowerBound
eupperBound
, respectivamente.
TreeMap
A classe TreeMap<K, V>
representa um mapeamento em forma de árvore. Ela herda de AbstractMap
e implementa NavigableMap
, o que inclui também SortedMap
. Diferentemente de HashMap
, em TreeMap
todos os objetos se ordenam automaticamente em ordem crescente de suas chaves.
TreeMap
possui construtores como:
TreeMap()
: cria um mapeamento vazio em forma de árvore.TreeMap(Map<? extends K, ? extends V> map)
: cria uma árvore e adiciona todos os elementos do mapeamentomap
.TreeMap(SortedMap<K, ? extends V> smap)
: cria uma árvore e adiciona todos os elementos do mapeamento ordenadosmap
.TreeMap(Comparator<? super K> comparator)
: cria uma árvore vazia, na qual os elementos adicionados serão ordenados pelo comparador.
Um exemplo de uso da classe segue abaixo.
import java.util.*;
public class Program {
public static void main(String[] args) {
TreeMap<Integer, String> states = new TreeMap<>();
states.put(10, "Germany");
states.put(2, "Spain");
states.put(14, "France");
states.put(3, "Italy");
// obtemos o objeto pela chave 2
String valueForKey2 = states.get(2);
System.out.println(valueForKey2);
// percorremos os elementos
for (Map.Entry<Integer, String> item : states.entrySet()) {
System.out.printf("Key: %d Value: %s \n", item.getKey(), item.getValue());
}
// obtemos o conjunto completo de chaves
Set<Integer> keys = states.keySet();
// obtemos a coleção de todos os valores
Collection<String> values = states.values();
// obtemos todos os objetos após a chave 4
Map<Integer, String> afterMap = states.tailMap(4);
// obtemos todos os objetos antes da chave 10
Map<Integer, String> beforeMap = states.headMap(10);
// obtemos o último elemento da árvore
Map.Entry<Integer, String> lastItem = states.lastEntry();
System.out.printf("Last item has key %d value %s \n", lastItem.getKey(), lastItem.getValue());
Map<String, Person> people = new TreeMap<>();
people.put("1240i54", new Person("Tom"));
people.put("1564i55", new Person("Bill"));
people.put("4540i56", new Person("Nick"));
for (Map.Entry<String, Person> item : people.entrySet()) {
System.out.printf("Key: %s Value: %s \n", item.getKey(), item.getValue().getName());
}
}
}
class Person {
private String name;
public Person(String name) {
this.name = name;
}
String getName() {
return name;
}
}
O código acima demonstra a principal característica do TreeMap
: a ordenação automática pelas chaves. Mesmo que os elementos sejam inseridos na ordem de chaves 10, 2, 14, 3
, ao percorrer o mapa com o for-each
sobre states.entrySet()
, a saída será impressa em ordem crescente das chaves: 2, 3, 10, 14
.
O exemplo também ilustra o uso de métodos de NavigableMap
. O método tailMap(4)
retorna um novo mapa contendo todos os elementos do mapa original com chave 4
ou superior. De forma similar, headMap(10)
retorna um mapa com os elementos cujas chaves são estritamente menores que 10
. O método lastEntry()
oferece acesso direto ao último par chave-valor do mapa ordenado. Por fim, o segundo mapa, que usa String
como chave e objetos Person
como valor, reforça que a ordenação é sempre baseada na ordem natural das chaves.
Resumo
SortedMap
: Interface que estendeMap
para mapeamentos ordenados por chaves em ordem crescente, com métodos para acessar submapeamentos.NavigableMap
: Extensão deSortedMap
que permite navegação relativa entre elementos, comoceiling
,floor
e submapeamentos inclusivos.TreeMap
: Classe que implementaNavigableMap
em estrutura de árvore, com ordenação automática de chaves e construtores para inicialização variada.
📝 Exercícios
Tarefa
Descrição: Você está criando um sistema de agendamento. Um TreeMap
armazena os horários de compromissos (chave Integer
representando a hora em formato 24h) e a descrição do evento (valor String
). Sua tarefa é encontrar o próximo compromisso disponível a partir de um horário específico.
Código inicial:
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
TreeMap<Integer, String> agenda = new TreeMap<>();
agenda.put(9, "Reunião de equipe");
agenda.put(11, "Entrevista com candidato");
agenda.put(14, "Almoço com cliente");
agenda.put(16, "Apresentação de projeto");
int horarioAtual = 12; // São 12:00
Map.Entry<Integer, String> proximoCompromisso = null;
// Use um método de NavigableMap para encontrar o primeiro compromisso
// que ocorre em um horário maior ou igual ao 'horarioAtual'.
if (proximoCompromisso != null) {
System.out.println("Seu próximo compromisso é às " + proximoCompromisso.getKey() + "h: " + proximoCompromisso.getValue());
} else {
System.out.println("Você não tem mais compromissos hoje.");
}
}
}
Resposta
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
TreeMap<Integer, String> agenda = new TreeMap<>();
agenda.put(9, "Reunião de equipe");
agenda.put(11, "Entrevista com candidato");
agenda.put(14, "Almoço com cliente");
agenda.put(16, "Apresentação de projeto");
int horarioAtual = 12;
// O método ceilingEntry(K key) é perfeito para encontrar o "próximo item a partir de um ponto".
// Ele retorna o par chave-valor com a menor chave que é maior ou igual à chave fornecida.
Map.Entry<Integer, String> proximoCompromisso = agenda.ceilingEntry(horarioAtual);
if (proximoCompromisso != null) {
System.out.println("Seu próximo compromisso é às " + proximoCompromisso.getKey() + "h: " + proximoCompromisso.getValue());
} else {
System.out.println("Você não tem mais compromissos hoje.");
}
}
}
Seu próximo compromisso é às 14h: Almoço com cliente
TreeMap
(que implementa NavigableMap
). O método ceilingEntry(12)
procura no mapa ordenado pelo primeiro par chave-valor cuja chave seja maior ou igual a 12. Ele encontra eficientemente a entrada com a chave 14
e a retorna, resolvendo o problema de forma concisa e performática.