-
Notifications
You must be signed in to change notification settings - Fork 3
05. Java Collection Frameworks
El Framework de Colecciones en Java es una biblioteca integral que ofrece una amplia gama de estructuras de datos y algoritmos diseñados para gestionar conjuntos de datos de manera eficiente. Permiten simplificar y optimizar el código.
Una colección es un objeto que agrupa múltiples elementos para luego manipularlos de manera conjunta. En java se usan para almacenar, organizar y manipular conjuntos de datos de manera eficiente.
-
Tamaño Dinámico
- Crecen o disminuyen según las necesidades, a diferencia de los arrays de tamaño fijo.
-
Facilidad de Uso
- Incluyen métodos para agregar, eliminar, buscar y ordenar elementos, simplificando su manejo.
-
Polimorfismo
- Permiten usar diferentes tipos de colecciones a través de interfaces comunes como
ListoSet.
- Permiten usar diferentes tipos de colecciones a través de interfaces comunes como
-
Seguridad de Tipo
- Con genéricos, garantizan que solo contengan elementos del tipo especificado, evitando errores.
-
Algoritmos Optimizados
- Proporcionan métodos eficientes para búsqueda, ordenación y eliminación de duplicados.
Ejemplo:
Array:
int[] numeros = new int[5];
numeros[0] = 10; Colección:
List<Integer> numeros = new ArrayList<>();
numeros.add(10); El framework proporciona una serie de interfaces, clases y enums que representan diferentes tipos de colecciones y algoritmos para manipularlas.

Algunas de las interfaces principales:
- Collection: Define operaciones básicas como agregar, eliminar y recorrer elementos.
- List: Colección ordenada que permite duplicados y acceso por índices.
- Set: Colección sin duplicados y sin orden específico.
- Map: Estructura de llave-valor que asocia claves únicas con valores.
| Método | Tipo de Dato Retornado | Descripción |
|---|---|---|
add(E e) |
boolean |
Agrega un elemento a la colección. |
remove(Object o) |
boolean |
Elimina un elemento específico de la colección. |
clear() |
void |
Remueve todos los elementos de una lista o conjunto. |
size() |
int |
Devuelve el número de elementos en la colección. |
contains(Object o) |
boolean |
Verifica si la colección contiene un elemento específico. |
reverse(List<T> lista) |
void |
Invierte el orden de los elementos en una lista. |
reverseOrder() |
Comparator |
Retorna un comparator que invierte el orden de los elementos de una colección. |
isEmpty() |
boolean |
Devuelve true si la colección está vacía. |
fill(List<T> lista, Objeto objeto) |
void |
Reemplaza todos los elementos de una lista con un elemento específico. |
addAll(Collection<? extends E> c) |
boolean |
Agrega todos los elementos de otra colección. |
removeAll(Collection<?> c) |
boolean |
Elimina todos los elementos que también están en la colección especificada. |
retainAll(Collection<?> c) |
boolean |
Retiene solo los elementos que están contenidos en la colección especificada. |
toArray() |
Object[] |
Convierte la colección en un array de objetos. |
toArray(T[] a) |
T[] |
Convierte la colección en un array del tipo especificado. |
Note
💡 Retroalimentación en Métodos add y remove
Los métodos add y remove en colecciones devuelven un valor booleano que indica el éxito de la operación:
-
add: Devuelvetruesi el elemento fue agregado exitosamente. -
remove: Devuelvetruesi el elemento fue eliminado con éxito.
Los Iterators permiten recorrer colecciones de forma secuencial, ofreciendo métodos como:
-
hasNext(): Verifica si hay más elementos. -
next(): Obtiene el siguiente elemento.
Se prefieren sobre los bucles for o foreach cuando es necesario modificar la colección (agregar o eliminar elementos) durante la iteración, ya que estos bucles no lo permiten.
La interfaz List representa una colección ordenada secuencialmente que permite duplicados y proporciona un acceso basado en índices a sus elementos. Al igual que los arrays, su índice comienza en 0.
Métodos propios en List:
| Método | Descripción | Tipo de Retorno |
|---|---|---|
void add(int index, E element) |
Inserta un elemento en la posición especificada de la lista. | void |
boolean addAll(int index, Collection<? extends E> c) |
Inserta todos los elementos de una colección en la posición indicada de la lista. | boolean |
E get(int index) |
Devuelve el elemento en la posición especificada. | E |
int indexOf(Object o) |
Devuelve el índice de la primera ocurrencia del elemento especificado. | int |
int lastIndexOf(Object o) |
Devuelve el índice de la última ocurrencia del elemento especificado. | int |
ListIterator<E> listIterator() |
Devuelve un iterador de lista para recorrer los elementos. | ListIterator<E> |
ListIterator<E> listIterator(int index) |
Devuelve un iterador de lista comenzando en la posición especificada. | ListIterator<E> |
E remove(int index) |
Elimina el elemento en la posición especificada de la lista. | E |
E set(int index, E element) |
Reemplaza el elemento en la posición especificada por otro elemento. | E |
void sort(List<T> lista) |
Ordena los elementos de la lista en orden ascendente. | void |
void shuffle(List<T> lista) |
Reorganiza aleatoriamente los elementos de la lista. | void |
List<E> subList(int fromIndex, int toIndex) |
Devuelve una vista de la lista entre los índices fromIndex (inclusive) y toIndex (exclusivo). |
List<E> |
El ArrayList es una implementación de la interfaz List en Java, que se basa en arreglos dinámicos para almacenar elementos de manera ordenada. A diferencia de los arreglos estáticos, los ArrayLists pueden crecer o reducirse dinámicamente según sea necesario.
Tiene como beneficios:
- Capacidad Inicial Personalizable: Permite definir una capacidad inicial para optimizar el rendimiento y evitar reasignaciones frecuentes de memoria.
-
Operaciones Específicas: Soporta métodos como
add(index, element)yremove(index)para manipular elementos en posiciones específicas. - Acceso Eficiente por Índice: Utiliza un arreglo interno que facilita el acceso rápido a los elementos mediante índices.
-
Soporte para Duplicados: Permite elementos duplicados, a diferencia de implementaciones como
Set, que los prohíben.
import java.util.ArrayList;
public class App {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<>();
lista.add("Manzana");
lista.add("Banana");
lista.add("Naranja");
System.out.println("Lista después de agregar elementos: " + lista);
}
}import java.util.ArrayList;
public class App {
public static void main(String[] args) {
ArrayList<Integer> numeros = new ArrayList<>();
numeros.add(10);
numeros.add(20);
numeros.add(30);
System.out.println("Lista original: " + numeros);
numeros.remove(1); // Elimina el elemento en índice 1 (20)
System.out.println("Lista después de eliminar: " + numeros);
}
}import java.util.ArrayList;
public class App {
public static void main(String[] args) {
ArrayList<Double> precios = new ArrayList<>();
precios.add(10.5);
precios.add(20.75);
precios.add(30.0);
double precio = precios.get(1); // Obtiene el elemento en índice 1 (20.75)
System.out.println("Precio obtenido: " + precio);
}
}import java.util.ArrayList;
public class App {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<>();
if (lista.isEmpty()) {
System.out.println("La lista está vacía.");
}
lista.add("Elemento1");
System.out.println("Lista actual: " + lista);
System.out.println("¿Lista vacía? " + lista.isEmpty());
}
}import java.util.ArrayList;
public class App {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<>();
lista.add("Manzana");
lista.add("Banana");
lista.add("Naranja");
System.out.println("Número de elementos en la lista: " + lista.size());
}
}import java.util.ArrayList;
import java.util.Collections;
public class App {
public static void main(String[] args) {
ArrayList<String> lista = new ArrayList<>();
lista.add("Banana");
lista.add("Manzana");
lista.add("Naranja");
Collections.sort(lista); // Orden alfabético
System.out.println("Lista ordenada: " + lista);
ArrayList<Integer> numeros = new ArrayList<>();
numeros.add(5);
numeros.add(2);
numeros.add(8);
Collections.sort(numeros); // Ascendente
System.out.println("Números en orden ascendente: " + numeros);
Collections.sort(numeros, Collections.reverseOrder()); // Descendente
System.out.println("Números en orden descendente: " + numeros);
}
}Clase Persona:
public class Persona {
private int documento;
private String nombre;
private String apellido;
public Persona(int documento, String nombre, String apellido) {
this.documento = documento;
this.nombre = nombre;
this.apellido = apellido;
}
public int getDocumento() {
return documento;
}
public String getNombre() {
return nombre;
}
public String getApellido() {
return apellido;
}
@Override
public String toString() {
return apellido + ", " + nombre + " (" + documento + ")";
}
}Clase principal (App):
import java.util.ArrayList;
public class App {
public static void main(String[] args) {
Persona p1 = new Persona(111, "Juan", "Pérez");
Persona p2 = new Persona(222, "Ana", "Gómez");
Persona p3 = new Persona(333, "Luis", "Martínez");
ArrayList<Persona> personas = new ArrayList<>();
personas.add(p1);
personas.add(p2);
personas.add(p3);
System.out.println("Lista inicial:");
imprimirLista(personas);
personas.remove(p2); // Eliminar un objeto
System.out.println("Lista después de eliminar:");
imprimirLista(personas);
}
public static void imprimirLista(ArrayList<Persona> lista) {
for (Persona p : lista) {
System.out.println(p);
}
System.out.println("-------------------");
}
}Los conjuntos son estructuras de datos clave en programación, diseñadas para almacenar elementos únicos, sin duplicados. Son ideales para situaciones donde la singularidad es esencial, como gestionar identificadores únicos, listas de reproducción sin repeticiones, o eliminar duplicados en datos.
Un Set es una colección que garantiza la exclusión de elementos duplicados mediante el método add(), que devuelve false si el elemento ya existe en el conjunto. La unicidad se define a través de los métodos equals() y hashCode(). Dos objetos diferentes pueden considerarse iguales si su implementación de equals() así lo especifica, incluso con atributos distintos.
HashSet es una implementación de la interfaz Set del paquete java.util, basada en tablas hash. A diferencia de otras implementaciones como TreeSet, no mantiene un orden específico en los elementos, pero garantiza la unicidad.
Note
💡 Una tabla hash es una estructura de datos que usa una función hash para calcular un índice basado en una clave, indicando dónde almacenar o buscar un dato en memoria. Esto permite un acceso rápido y eficiente. Si dos claves generan el mismo índice (colisión), se utilizan métodos como listas enlazadas o búsqueda de otro espacio disponible para resolverlo, asegurando su funcionalidad.
- Unicidad de Elementos: Evita elementos duplicados; no agrega elementos ya presentes.
- Eficiencia: Operaciones como agregar, eliminar o buscar se realizan en tiempo constante promedio gracias a su implementación basada en tablas hash.
- No Garantiza Orden: Los elementos no siguen un orden de inserción ni un orden natural.
-
Soporte para Objetos Personalizados: Permite trabajar con objetos personalizados que implementen correctamente
hashCodeyequals. - Casos de Uso: Ideal para verificar pertenencia rápida o eliminar duplicados en grandes conjuntos de datos.
- Crear un
HashSetde enteros:
import java.util.HashSet;
public class EjemploHashSet {
public static void main(String[] args) {
// Crear un HashSet vacío de enteros
HashSet<Integer> numeros = new HashSet<>();
}
}- Agregar Elementos (
add):
numeros.add(10); // Agregar un número al HashSet
numeros.add(20);
numeros.add(30);
System.out.println(numeros); // Salida: [10, 20, 30]- Eliminar Elementos (
remove):
numeros.remove(20); // Eliminar el número 20
System.out.println(numeros); // Salida: [10, 30]- Verificar la Existencia (
contains):
boolean existe = numeros.contains(10); // Verifica si el número 10 está en el HashSet
System.out.println(existe); // Salida: true- Obtener el Tamaño (
size):
int tamano = numeros.size(); // Obtiene el tamaño del HashSet
System.out.println(tamano); // Salida: 2- Iteración a través del
HashSet:
for (int numero : numeros) {
System.out.println(numero); // Itera y muestra cada elemento
}
// Salida:
// 10
// 30
// Iterar a través del HashSet usando un Iterator (como un bucle for-each)
Iterator<Integer> iterador = numeros.iterator();
while (iterador.hasNext()) {
int numero = iterador.next();
System.out.println(numero); // Salida: 10, 30
}HashSet es una implementación de la interfaz Set en Java que utiliza una tabla hash para almacenar elementos de forma única. Los métodos hashCode() y equals() son fundamentales para su funcionamiento:
-
hashCode(): Calcula un valor hash que se utiliza para determinar la ubicación del elemento en la tabla hash. Este valor debe ser único para optimizar el acceso. -
equals(): Comprueba la igualdad lógica entre dos objetos. Cuando se agrega un elemento, primero se calcula suhashCode(). Si ya existe un elemento con el mismo hash,equals()verifica si son iguales, evitando duplicados.
Ejemplo:
import java.util.HashSet;
class Libro {
private String titulo;
private String autor;
private int ISBN;
public Libro(String titulo, String autor, int ISBN) {
this.titulo = titulo;
this.autor = autor;
this.ISBN = ISBN;
}
@Override
public int hashCode() {
return ISBN; // El ISBN actúa como identificador único
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
// getClass() obtiene la clase real del objeto en tiempo de ejecución.
if (obj == null || getClass() != obj.getClass()) return false;
Libro otroLibro = (Libro) obj;
return ISBN == otroLibro.ISBN;
}
}
public class Main {
public static void main(String[] args) {
HashSet<Libro> set = new HashSet<>();
// Crear libros
Libro libro1 = new Libro("Cien años de soledad", "Gabriel García Márquez", 123456789);
Libro libro2 = new Libro("El Principito", "Antoine de Saint-Exupéry", 987654321);
// Agregar libros al HashSet
set.add(libro1);
set.add(libro2);
// Verificar si un libro está presente
Libro libro3 = new Libro("Cien años de soledad", "Gabriel García Márquez", 123456789);
System.out.println("¿Contiene libro3?: " + set.contains(libro3)); // true
// Eliminar un libro
set.remove(libro2);
System.out.println("Tamaño del HashSet: " + set.size()); // 1
}
}
- Clase
Libro: SobrescribehashCode()para usar el ISBN como identificador único yequals()para verificar igualdad lógica.- Operaciones: -
add(): Agrega libros, pero evita duplicados basados en el ISBN. -contains(): Comprueba si un libro con el mismo ISBN ya existe. -remove(): Elimina libros por su ISBN.
Un Map en Java es una interfaz que almacena pares clave-valor, donde cada clave es única y está asociada a un único valor. Se utiliza para acceder eficientemente a los valores mediante sus claves. No permite claves duplicadas.
Un HashMap es una implementación de la interfaz Map que utiliza una función hash para calcular un índice, almacenando los pares clave-valor de manera eficiente. Permite un acceso rápido y constante a los valores mediante sus claves.
Un HashMap es ideal para:
- Asociación de Datos: Asociar rápidamente claves a valores, como configuraciones o cachés.
-
Eficiencia en Búsquedas: Operaciones como
put,get, yremovetienen tiempo promedio constante O(1)O(1). - Asociaciones Uno a Uno: Garantiza que cada clave tiene exactamente un valor único asociado.
| Método | Descripción |
|---|---|
put(K key, V value) |
Agrega o actualiza un par clave-valor. Devuelve el valor anterior o null si la clave es nueva. |
get(Object key) |
Recupera el valor asociado a una clave. Devuelve null si no existe la clave. |
remove(Object key) |
Elimina un par clave-valor. Devuelve el valor eliminado o null si no existe. |
containsKey(Object key) |
Verifica si una clave está presente en el mapa. |
size() |
Retorna el número de pares clave-valor. |
isEmpty() |
Retorna true si el mapa está vacío. |
clear() |
Elimina todos los pares clave-valor del mapa. |
values() |
Devuelve una colección de los valores almacenados. |
replace(K key, V value) |
Reemplaza el valor asociado con una clave. Devuelve el valor anterior o null si no existe. |
Ejemplo de uso:
import java.util.HashMap;
public class EjemploHashMap {
public static void main(String[] args) {
// Crear un HashMap
HashMap<String, Integer> inventario = new HashMap<>();
// Agregar elementos
inventario.put("Manzanas", 50);
inventario.put("Naranjas", 30);
inventario.put("Peras", 20);
// Obtener un valor
System.out.println("Cantidad de Naranjas: " + inventario.get("Naranjas")); // 30
// Reemplazar un valor
inventario.replace("Manzanas", 60);
System.out.println("Cantidad de Manzanas actualizada: " + inventario.get("Manzanas")); // 60
// Verificar si contiene una clave
System.out.println("¿Contiene 'Peras'? " + inventario.containsKey("Peras")); // true
// Eliminar un elemento
inventario.remove("Naranjas");
System.out.println("Inventario después de eliminar Naranjas: " + inventario);
// Obtener el tamaño
System.out.println("Tamaño del inventario: " + inventario.size()); // 2
// Iterar sobre el HashMap
System.out.println("Inventario:");
for (String clave : inventario.keySet()) {
System.out.println(clave + ": " + inventario.get(clave));
}
}
}Salida:
Cantidad de Naranjas: 30
Cantidad de Manzanas actualizada: 60
¿Contiene 'Peras'? true
Inventario después de eliminar Naranjas: {Manzanas=60, Peras=20}
Tamaño del inventario: 2
Inventario:
Manzanas: 60
Peras: 20