Java TreeMap: Domina Mapas Ordenados con Ejemplos Prácticos
Java TreeMap
Explora la clase TreeMap de Java – una implementación de mapa naturalmente ordenada y potente – con ejemplos claros, operaciones clave y técnicas avanzadas de navegación.
La clase TreeMap es parte del Framework de Colecciones de Java y proporciona una implementación de árbol rojo-negro que mantiene sus entradas ordenadas según el orden natural de las claves o un Comparator personalizado. Implementa la interfaz NavigableMap, que añade métodos convenientes para recorrer y consultar el mapa.
Creando un TreeMap
Antes de poder usar un TreeMap, importa el paquete:
import java.util.TreeMap;
Luego crea una instancia:
TreeMap<Clave, Valor> numeros = new TreeMap<>();
Por defecto, las claves se ordenan en orden natural ascendente. Si necesitas un orden personalizado, pasa un Comparator al constructor.
- Clave – identificador único para cada entrada.
- Valor – dato asociado con la clave.
Resumen de Métodos de TreeMap
La clase ofrece un rico conjunto de operaciones. A continuación, categorías clave con fragmentos de código.
Insertando Elementos
put()– añade o reemplaza un par clave/valor.putAll()– fusiona otro mapa en este.putIfAbsent()– inserta solo si la clave falta.
Ejemplo:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numerosPares = new TreeMap<>();
numerosPares.put("Dos", 2);
numerosPares.put("Cuatro", 4);
numerosPares.putIfAbsent("Seis", 6);
System.out.println("TreeMap de números pares: " + numerosPares);
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Uno", 1);
numeros.putAll(numerosPares);
System.out.println("TreeMap de números: " + numeros);
}
}
Salida
TreeMap de números pares: {Cuatro=4, Seis=6, Dos=2} TreeMap de números: {Cuatro=4, Uno=1, Seis=6, Dos=2}
Accediendo a Elementos
Usando Vistas de Colección
entrySet()– devuelve todos los pares clave/valor.keySet()– devuelve todas las claves.values()– devuelve todos los valores.
Ejemplo:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Uno", 1);
numeros.put("Dos", 2);
numeros.put("Tres", 3);
System.out.println("TreeMap: " + numeros);
System.out.println("Mapeos Clave/Valor: " + numeros.entrySet());
System.out.println("Claves: " + numeros.keySet());
System.out.println("Valores: " + numeros.values());
}
}
Salida
TreeMap: {Uno=1, Tres=3, Dos=2} Mapeos Clave/Valor: [Uno=1, Tres=3, Dos=2] Claves: [Uno, Tres, Dos] Valores: [1, 3, 2]
Recuperando Valores
get()– devuelve el valor para una clave onullsi está ausente.getOrDefault()– devuelve un default si la clave falta.
Ejemplo:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Uno", 1);
numeros.put("Dos", 2);
numeros.put("Tres", 3);
System.out.println("TreeMap: " + numeros);
int valor1 = numeros.get("Tres");
System.out.println("Usando get(): " + valor1);
int valor2 = numeros.getOrDefault("Cinco", 5);
System.out.println("Usando getOrDefault(): " + valor2);
}
}
Salida
TreeMap: {Uno=1, Tres=3, Dos=2} Usando get(): 3 Usando getOrDefault(): 5
Eliminando Entradas
remove(clave)– elimina la entrada y devuelve su valor.remove(clave, valor)– elimina solo si la clave mapea al valor especificado.
Ejemplo:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Uno", 1);
numeros.put("Dos", 2);
numeros.put("Tres", 3);
System.out.println("TreeMap: " + numeros);
int eliminado = numeros.remove("Dos");
System.out.println("Valor eliminado: " + eliminado);
boolean eliminadoPar = numeros.remove("Tres", 3);
System.out.println("¿Se eliminó la entrada {Tres=3}? " + eliminadoPar);
System.out.println("TreeMap Actualizado: " + numeros);
}
}
Salida
TreeMap: {Uno=1, Tres=3, Dos=2} Valor eliminado: 2 ¿Se eliminó la entrada {Tres=3}? true TreeMap Actualizado: {Uno=1}
Reemplazando Valores
replace(clave, valor)– actualiza el valor para una clave.replace(clave, antiguo, nuevo)– actualiza solo si el valor actual coincide conantiguo.replaceAll(función)– aplica una función a cada entrada.
Ejemplo:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Primero", 1);
numeros.put("Segundo", 2);
numeros.put("Tercero", 3);
System.out.println("TreeMap Original: " + numeros);
numeros.replace("Segundo", 22);
numeros.replace("Tercero", 3, 33);
System.out.println("Después de replace(): " + numeros);
numeros.replaceAll((k, v) -> v + 2);
System.out.println("Después de replaceAll(): " + numeros);
}
}
Salida
TreeMap Original: {Primero=1, Segundo=2, Tercero=3} Después de replace(): {Primero=1, Segundo=22, Tercero=33} Después de replaceAll(): {Primero=3, Segundo=24, Tercero=35}
Métodos de Navegación
Como TreeMap implementa NavigableMap, ofrece métodos para consultar la estructura eficientemente.
Primer y Último Elementos
firstKey()– primera clave en orden.firstEntry()– entrada para la primera clave.lastKey()– última clave.lastEntry()– entrada para la última clave.
Ejemplo:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Primero", 1);
numeros.put("Segundo", 2);
numeros.put("Tercero", 3);
System.out.println("TreeMap: " + numeros);
System.out.println("Primera Clave: " + numeros.firstKey());
System.out.println("Última Clave: " + numeros.lastKey());
System.out.println("Primera Entrada: " + numeros.firstEntry());
System.out.println("Última Entrada: " + numeros.lastEntry());
}
}
Salida
TreeMap: {Primero=1, Segundo=2, Tercero=3} Primera Clave: Primero Última Clave: Tercero Primera Entrada: Primero=1 Última Entrada: Tercero=3
Ceiling, Floor, Higher y Lower
Estos métodos devuelven claves o entradas relativas a una clave dada, facilitando consultas de rango.
higherKey(),higherEntry()– siguiente clave/entrada superior.lowerKey(),lowerEntry()– clave/entrada anterior inferior.ceilingKey(),ceilingEntry()– clave/entrada más pequeña ≥ clave dada.floorKey(),floorEntry()– clave/entrada más grande ≤ clave dada.
Ejemplo:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Primero", 1);
numeros.put("Segundo", 5);
numeros.put("Tercero", 4);
numeros.put("Cuarto", 6);
System.out.println("TreeMap: " + numeros);
System.out.println("higherKey('Cuarto'): " + numeros.higherKey("Cuarto"));
System.out.println("higherEntry('Cuarto'): " + numeros.higherEntry("Cuarto"));
System.out.println("lowerKey('Cuarto'): " + numeros.lowerKey("Cuarto"));
System.out.println("lowerEntry('Cuarto'): " + numeros.lowerEntry("Cuarto"));
System.out.println("ceilingKey('Cuarto'): " + numeros.ceilingKey("Cuarto"));
System.out.println("ceilingEntry('Cuarto'): " + numeros.ceilingEntry("Cuarto"));
System.out.println("floorKey('Cuarto'): " + numeros.floorKey("Cuarto"));
System.out.println("floorEntry('Cuarto'): " + numeros.floorEntry("Cuarto"));
}
}
Salida
TreeMap: {Primero=1, Cuarto=6, Segundo=5, Tercero=4} higherKey('Cuarto'): Segundo higherEntry('Cuarto'): Segundo=5 lowerKey('Cuarto'): Primero lowerEntry('Cuarto'): Primero=1 ceilingKey('Cuarto'): Cuarto ceilingEntry('Cuarto'): Cuarto=6 floorKey('Cuarto'): Cuarto floorEntry('Cuarto'): Cuarto=6
Polling y Rangos
pollFirstEntry() y pollLastEntry() eliminan y devuelven la primera/última entrada, respectivamente.
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Primero", 1);
numeros.put("Segundo", 2);
numeros.put("Tercero", 3);
System.out.println("TreeMap: " + numeros);
System.out.println("pollFirstEntry(): " + numeros.pollFirstEntry());
System.out.println("pollLastEntry(): " + numeros.pollLastEntry());
System.out.println("TreeMap Actualizado: " + numeros);
}
}
Salida
TreeMap: {Primero=1, Segundo=2, Tercero=3} pollFirstEntry(): Primero=1 pollLastEntry(): Tercero=3 TreeMap Actualizado: {Segundo=2}
headMap, tailMap, subMap
Estos métodos proporcionan vistas sobre rangos de claves específicos.
headMap(hastaClave, inclusivo)– claves < hastaClave (o ≤ si inclusivo).tailMap(desdeClave, inclusivo)– claves ≥ desdeClave (o > si exclusivo).subMap(desdeClave, desdeInclusivo, hastaClave, hastaInclusivo)– claves entre los dos límites.
Ejemplo:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>();
numeros.put("Primero", 1);
numeros.put("Segundo", 2);
numeros.put("Tercero", 3);
numeros.put("Cuarto", 4);
System.out.println("TreeMap: " + numeros);
System.out.println("headMap('Cuarto'): " + numeros.headMap("Cuarto"));
System.out.println("headMap('Cuarto', true): " + numeros.headMap("Cuarto", true));
System.out.println("tailMap('Segundo'): " + numeros.tailMap("Segundo"));
System.out.println("tailMap('Segundo', false): " + numeros.tailMap("Segundo", false));
System.out.println("subMap('Cuarto', true, 'Tercero', false): " + numeros.subMap("Cuarto", true, "Tercero", false));
}
}
Salida
TreeMap: {Primero=1, Cuarto=4, Segundo=2, Tercero=3} headMap('Cuarto'): {Primero=1} headMap('Cuarto', true): {Primero=1, Cuarto=4} tailMap('Segundo'): {Segundo=2, Tercero=3, Cuarto=4} tailMap('Segundo', false): {Tercero=3, Cuarto=4} subMap('Cuarto', true, 'Tercero', false): {Cuarto=4, Segundo=2}
Métodos de Utilidad Adicionales
| Método | Descripción |
|---|---|
clone() | Crea una copia superficial del mapa. |
containsKey() | Verifica presencia de una clave. |
containsValue() | Verifica un valor específico. |
size() | Devuelve el número de entradas. |
clear() | Elimina todas las entradas. |
Ordenamiento Personalizado de Claves con Comparator
Para ordenar claves de forma diferente—como orden inverso o strings case-insensitive—implementa Comparator y pásalo al constructor de TreeMap.
import java.util.TreeMap;
import java.util.Comparator;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numeros = new TreeMap<>(new ComparadorPersonalizado());
numeros.put("Primero", 1);
numeros.put("Segundo", 2);
numeros.put("Tercero", 3);
numeros.put("Cuarto", 4);
System.out.println("TreeMap: " + numeros);
}
static class ComparadorPersonalizado implements Comparator<String> {
@Override
public int compare(String a, String b) {
// Orden natural inverso
return a.compareTo(b) * -1;
}
}
}
Salida
TreeMap: {Tercero=3, Segundo=2, Cuarto=4, Primero=1}
Para más sobre Comparator, consulta la documentación oficial de Java.
Java
- Dominar Operadores en Java: Tipos, Sintaxis y Ejemplos Prácticos
- Comentarios en Java: Tipos, Uso y Mejores Prácticas
- Dominar el Bucle for Mejorado en Java: Sintaxis, Ejemplos y Mejores Prácticas
- Dominar Strings en Java: Creación, Métodos y Mejores Prácticas
- Dominando interfaces en Java: Conceptos, implementación y mejores prácticas
- Dominando las clases internas anónimas en Java: Definición, sintaxis y ejemplos prácticos
- Dominando Try‑with‑Resources en Java: Gestión automática de recursos explicada
- Anotaciones en Java explicadas: Tipos, ubicación y ejemplos prácticos
- Aserciones en Java: Guía práctica para detectar bugs y asegurar fiabilidad del código
- Dominando los Algoritmos de Colecciones de Java: Ordenación, Mezcla y Más
- Generar números aleatorios en Java: Guía práctica con Random y Math.random