Dominando Java TreeSet: Operaciones, Métodos y Ejemplos Prácticos
Java TreeSet
En este tutorial, aprenderemos sobre la clase TreeSet de Java y sus diversas operaciones y métodos con la ayuda de ejemplos.
La clase TreeSet del framework de colecciones de Java proporciona la funcionalidad de una estructura de datos de árbol.
Extiende la interfaz NavigableSet.
Crear un TreeSet
Para crear un conjunto de árbol, primero debemos importar el paquete java.util.TreeSet.
Una vez importado el paquete, así es como podemos crear un TreeSet en Java.
TreeSet<Integer> numeros = new TreeSet<>();
Aquí, hemos creado un TreeSet sin argumentos. En este caso, los elementos en TreeSet se ordenan naturalmente (orden ascendente).
Sin embargo, podemos personalizar la ordenación de elementos usando la interfaz Comparator. Lo aprenderemos más adelante en este tutorial.
Métodos de TreeSet
La clase TreeSet proporciona varios métodos que nos permiten realizar diversas operaciones en el conjunto.
Insertar Elementos en TreeSet
add()– inserta el elemento especificado en el conjuntoaddAll()– inserta todos los elementos de la colección especificada en el conjunto
Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numerosPares = new TreeSet<>();
// Usando el método add()
numerosPares.add(2);
numerosPares.add(4);
numerosPares.add(6);
System.out.println("TreeSet: " + numerosPares);
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(1);
// Usando el método addAll()
numeros.addAll(numerosPares);
System.out.println("Nuevo TreeSet: " + numeros);
}
}
Salida
TreeSet: [2, 4, 6] Nuevo TreeSet: [1, 2, 4, 6]
Acceder a Elementos de TreeSet
Para acceder a los elementos de un conjunto de árbol, podemos usar el método iterator(). Para usar este método, debemos importar el paquete java.util.Iterator. Por ejemplo,
import java.util.TreeSet;
import java.util.Iterator;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(2);
numeros.add(5);
numeros.add(6);
System.out.println("TreeSet: " + numeros);
// Llamando al método iterator()
Iterator<Integer> iterar = numeros.iterator();
System.out.print("TreeSet usando Iterator: ");
// Accediendo a elementos
while(iterar.hasNext()) {
System.out.print(iterar.next() + ", ");
}
}
}
Salida
TreeSet: [2, 5, 6] TreeSet usando Iterator: 2, 5, 6,
Eliminar Elementos
remove()– elimina el elemento especificado del conjuntoremoveAll()– elimina todos los elementos del conjunto
Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(2);
numeros.add(5);
numeros.add(6);
System.out.println("TreeSet: " + numeros);
// Usando el método remove()
boolean valor1 = numeros.remove(5);
System.out.println("¿Se eliminó el 5? " + valor1);
// Usando el método removeAll()
boolean valor2 = numeros.removeAll(numeros);
System.out.println("¿Se eliminaron todos los elementos? " + valor2);
}
}
Salida
TreeSet: [2, 5, 6] ¿Se eliminó el 5? true ¿Se eliminaron todos los elementos? true
Métodos para Navegación
Dado que la clase TreeSet implementa NavigableSet, proporciona varios métodos para navegar sobre los elementos del conjunto de árbol.
1. Métodos first() y last()
first()– retorna el primer elemento del conjuntolast()– retorna el último elemento del conjunto
Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(2);
numeros.add(5);
numeros.add(6);
System.out.println("TreeSet: " + numeros);
// Usando el método first()
int primero = numeros.first();
System.out.println("Primer Número: " + primero);
// Usando el método last()
int ultimo = numeros.last();
System.out.println("Último Número: " + ultimo);
}
}
Salida
TreeSet: [2, 5, 6] Primer Número: 2 Último Número: 6
2. Métodos ceiling(), floor(), higher() y lower()
- higher(elemento) – Retorna el elemento más bajo entre aquellos que son mayores que el
elementoespecificado. - lower(elemento) – Retorna el elemento más grande entre aquellos que son menores que el
elementoespecificado. - ceiling(elemento) – Retorna el elemento más bajo entre aquellos que son mayores o iguales al elemento especificado. Si el elemento pasado existe en el tree set, retorna el
elementopasado como argumento. - floor(elemento) – Retorna el elemento más grande entre aquellos que son menores o iguales al
elementoespecificado. Si el elemento pasado existe en un tree set, retorna elelementopasado como argumento.
Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(2);
numeros.add(5);
numeros.add(4);
numeros.add(6);
System.out.println("TreeSet: " + numeros);
// Usando higher()
System.out.println("Usando higher: " + numeros.higher(4));
// Usando lower()
System.out.println("Usando lower: " + numeros.lower(4));
// Usando ceiling()
System.out.println("Usando ceiling: " + numeros.ceiling(4));
// Usando floor()
System.out.println("Usando floor: " + numeros.floor(3));
}
}
Salida
TreeSet: [2, 4, 5, 6] Usando higher: 5 Usando lower: 2 Usando ceiling: 4 Usando floor: 2
3. Métodos pollFirst() y pollLast()
pollFirst()– retorna y elimina el primer elemento del conjuntopollLast()– retorna y elimina el último elemento del conjunto
Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(2);
numeros.add(5);
numeros.add(4);
numeros.add(6);
System.out.println("TreeSet: " + numeros);
// Usando pollFirst()
System.out.println("Primer Elemento Eliminado: " + numeros.pollFirst());
// Usando pollLast()
System.out.println("Último Elemento Eliminado: " + numeros.pollLast());
System.out.println("Nuevo TreeSet: " + numeros);
}
}
Salida
TreeSet: [2, 4, 5, 6] Primer Elemento Eliminado: 2 Último Elemento Eliminado: 6 Nuevo TreeSet: [4, 5]
4. Métodos headSet(), tailSet() y subSet()
headSet(elemento, valorBooleano)
El método headSet() retorna todos los elementos de un tree set antes del elemento especificado (que se pasa como argumento).
El parámetro valorBooleano es opcional. Su valor por defecto es false.
Si se pasa true como valorBooleano, el método retorna todos los elementos antes del elemento especificado incluyendo el elemento especificado.
Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(2);
numeros.add(5);
numeros.add(4);
numeros.add(6);
System.out.println("TreeSet: " + numeros);
// Usando headSet() con valor booleano por defecto
System.out.println("Usando headSet sin valor booleano: " + numeros.headSet(5));
// Usando headSet() con valor booleano especificado
System.out.println("Usando headSet con valor booleano: " + numeros.headSet(5, true));
}
}
Salida
TreeSet: [2, 4, 5, 6] Usando headSet sin valor booleano: [2, 4] Usando headSet con valor booleano: [2, 4, 5]
tailSet(elemento, valorBooleano)
El método tailSet() retorna todos los elementos de un tree set después del elemento especificado (que se pasa como parámetro) incluyendo el elemento especificado.
El parámetro valorBooleano es opcional. Su valor por defecto es true.
Si se pasa false como valorBooleano, el método retorna todos los elementos después del elemento especificado sin incluir el elemento especificado.
Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(2);
numeros.add(5);
numeros.add(4);
numeros.add(6);
System.out.println("TreeSet: " + numeros);
// Usando tailSet() con valor booleano por defecto
System.out.println("Usando tailSet sin valor booleano: " + numeros.tailSet(4));
// Usando tailSet() con valor booleano especificado
System.out.println("Usando tailSet con valor booleano: " + numeros.tailSet(4, false));
}
}
Salida
TreeSet: [2, 4, 5, 6] Usando tailSet sin valor booleano: [4, 5, 6] Usando tailSet con valor booleano: [5, 6]
subSet(e1, bv1, e2, bv2)
El método subSet() retorna todos los elementos entre e1 y e2 incluyendo e1.
Los parámetros bv1 y bv2 son opcionales. El valor por defecto de bv1 es true, y el valor por defecto de bv2 es false.
Si se pasa false como bv1, el método retorna todos los elementos entre e1 y e2 sin incluir e1.
Si se pasa true como bv2, el método retorna todos los elementos entre e1 y e2, incluyendo e1.
Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(2);
numeros.add(5);
numeros.add(4);
numeros.add(6);
System.out.println("TreeSet: " + numeros);
// Usando subSet() con valor booleano por defecto
System.out.println("Usando subSet sin valor booleano: " + numeros.subSet(4, 6));
// Usando subSet() con valor booleano especificado
System.out.println("Usando subSet con valor booleano: " + numeros.subSet(4, false, 6, true));
}
}
Salida
TreeSet: [2, 4, 5, 6] Usando subSet sin valor booleano: [4, 5] Usando subSet con valor booleano: [5, 6]
Operaciones de Conjunto
Los métodos de la clase TreeSet también se pueden usar para realizar diversas operaciones de conjunto.
Unión de Conjuntos
Para realizar la unión entre dos conjuntos, usamos el método addAll(). Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numerosPares = new TreeSet<>();
numerosPares.add(2);
numerosPares.add(4);
System.out.println("TreeSet1: " + numerosPares);
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(1);
numeros.add(2);
numeros.add(3);
System.out.println("TreeSet2: " + numeros);
// Unión de dos conjuntos
numeros.addAll(numerosPares);
System.out.println("La unión es: " + numeros);
}
}
Salida
TreeSet1: [2, 4] TreeSet2: [1, 2, 3] La unión es: [1, 2, 3, 4]
Intersección de Conjuntos
Para realizar la intersección entre dos conjuntos, usamos el método retainAll(). Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numerosPares = new TreeSet<>();
numerosPares.add(2);
numerosPares.add(4);
System.out.println("TreeSet1: " + numerosPares);
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(1);
numeros.add(2);
numeros.add(3);
System.out.println("TreeSet2: " + numeros);
// Intersección de dos conjuntos
numeros.retainAll(numerosPares);
System.out.println("La intersección es: " + numeros);
}
}
Salida
TreeSet1: [2, 4] TreeSet2: [1, 2, 3] La intersección es: [2]
Diferencia de Conjuntos
Para calcular la diferencia entre dos conjuntos, podemos usar el método removeAll(). Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numerosPares = new TreeSet<>();
numerosPares.add(2);
numerosPares.add(4);
System.out.println("TreeSet1: " + numerosPares);
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(1);
numeros.add(2);
numeros.add(3);
numeros.add(4);
System.out.println("TreeSet2: " + numeros);
// Diferencia entre dos conjuntos
numeros.removeAll(numerosPares);
System.out.println("La diferencia es: " + numeros);
}
}
Salida
TreeSet1: [2, 4] TreeSet2: [1, 2, 3, 4] La diferencia es: [1, 3]
Subconjunto de un Conjunto
Para verificar si un conjunto es subconjunto de otro conjunto, usamos el método containsAll(). Por ejemplo,
import java.util.TreeSet;
class Main {
public static void main(String[] args) {
TreeSet<Integer> numeros = new TreeSet<>();
numeros.add(1);
numeros.add(2);
numeros.add(3);
numeros.add(4);
System.out.println("TreeSet1: " + numeros);
TreeSet<Integer> numerosPrimos = new TreeSet<>();
numerosPrimos.add(2);
numerosPrimos.add(3);
System.out.println("TreeSet2: " + numerosPrimos);
// Verificar si numerosPrimos es subconjunto de numeros
boolean resultado = numeros.containsAll(numerosPrimos);
System.out.println("¿TreeSet2 es subconjunto de TreeSet1? " + resultado);
}
}
Salida
TreeSet1: [1, 2, 3, 4] TreeSet2: [2, 3] ¿TreeSet2 es subconjunto de TreeSet1? true
Otros Métodos de TreeSet
| Método | Descripción |
|---|---|
clone() | Crea una copia del TreeSet |
contains() | Busca el elemento especificado en el TreeSet y retorna un resultado booleano |
isEmpty() | Verifica si el TreeSet está vacío |
size() | Retorna el tamaño del TreeSet |
clear() | Elimina todos los elementos del TreeSet |
Para aprender más, visita la documentación oficial de Java TreeSet.
TreeSet vs HashSet
Tanto TreeSet como HashSet implementan la interfaz Set. Sin embargo, existen algunas diferencias entre ellos.
- A diferencia de
HashSet, los elementos enTreeSetse almacenan en algún orden. Es porqueTreeSettambién implementa la interfazSortedSet. TreeSetproporciona algunos métodos para navegación fácil. Por ejemplo,first(),last(),headSet(),tailSet(), etc. Es porqueTreeSettambién implementa la interfazNavigableSet.HashSetes más rápido queTreeSetpara operaciones básicas como add, remove, contains y size.
Comparador de TreeSet
En todos los ejemplos anteriores, los elementos del tree set se ordenan naturalmente. Sin embargo, también podemos personalizar el orden de los elementos.
Para esto, necesitamos crear nuestra propia clase comparadora basada en la cual los elementos en un tree set se ordenan. Por ejemplo,
import java.util.TreeSet;
import java.util.Comparator;
class Main {
public static void main(String[] args) {
// Crear un tree set con comparador personalizado
TreeSet<String> animales = new TreeSet<>(new ComparadorPersonalizado());
animales.add("Perro");
animales.add("Cebra");
animales.add("Gato");
animales.add("Caballo");
System.out.println("TreeSet: " + animales);
}
// Crear una clase comparadora
public static class ComparadorPersonalizado implements Comparator<String> {
@Override
public int compare(String animal1, String animal2) {
int valor = animal1.compareTo(animal2);
// Los elementos se ordenan en orden inverso
if (valor > 0) {
return -1;
} else if (valor < 0) {
return 1;
} else {
return 0;
}
}
}
}
Salida
TreeSet: [Cebra, Caballo, Perro, Gato]
En el ejemplo anterior, hemos creado un tree set pasando la clase ComparadorPersonalizado como argumento.
La clase ComparadorPersonalizado implementa la interfaz Comparator.
Luego sobrescribimos el método compare(). El método ahora ordenará los elementos en orden inverso.
Para aprender más, visita la documentación oficial de Java Comparator.
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