Rust
Tutorial Rust: Colecciones estándar
Aprende a usar colecciones estándar en Rust como Vec, HashMap y HashSet para gestionar datos dinámicos y eficientes.
Aprende Rust y certifícateVec<T>
El vector es una de las estructuras de datos más utilizadas en Rust. Un Vec<T>
es una colección dinámica que almacena elementos del mismo tipo T
de forma contigua en memoria, similar a los arrays pero con la capacidad de crecer o reducir su tamaño durante la ejecución del programa.
A diferencia de los arrays que tienen un tamaño fijo definido en tiempo de compilación, los vectores permiten añadir o eliminar elementos según sea necesario. Esta flexibilidad los convierte en una herramienta fundamental para cuando no conocemos de antemano cuántos elementos necesitaremos almacenar.
Creación de vectores
Existen varias formas de crear un nuevo vector:
// Vector vacío
let mut numeros: Vec<i32> = Vec::new();
// Vector con capacidad inicial reservada
let mut nombres: Vec<String> = Vec::with_capacity(10);
// Vector con valores iniciales usando macro vec!
let colores = vec!["rojo", "verde", "azul"];
El macro vec!
proporciona una sintaxis concisa para crear vectores con valores iniciales. Rust inferirá automáticamente el tipo de los elementos basándose en los valores proporcionados.
Añadir elementos
Para añadir elementos a un vector, necesitamos declararlo como mutable usando mut
:
let mut frutas = Vec::new();
// Añadir elementos al final del vector
frutas.push("manzana");
frutas.push("naranja");
frutas.push("plátano");
println!("Tenemos {} frutas", frutas.len()); // Imprime: Tenemos 3 frutas
También podemos añadir múltiples elementos de una vez:
let mut numeros = vec![1, 2];
numeros.extend([3, 4, 5].iter());
println!("{:?}", numeros); // Imprime: [1, 2, 3, 4, 5]
Acceso a elementos
Podemos acceder a los elementos de un vector de dos formas principales:
- Mediante indexación con corchetes
[]
- Usando el método
get
let vocales = vec!['a', 'e', 'i', 'o', 'u'];
// Acceso por índice (puede causar pánico si el índice está fuera de rango)
let primera = vocales[0]; // 'a'
// Acceso seguro con get (devuelve Option<&T>)
match vocales.get(1) {
Some(valor) => println!("El segundo elemento es: {}", valor),
None => println!("No existe ese elemento"),
}
// También podemos usar if let para un código más conciso
if let Some(valor) = vocales.get(10) {
println!("Elemento encontrado: {}", valor);
} else {
println!("Índice fuera de rango");
}
La diferencia clave entre estos métodos es que la indexación directa causará que el programa termine abruptamente (panic) si intentamos acceder a un índice fuera de rango, mientras que el método get
devuelve un Option<&T>
que podemos manejar de forma segura.
Eliminar elementos
Rust ofrece varios métodos para eliminar elementos de un vector:
let mut numeros = vec![10, 20, 30, 40, 50];
// Eliminar y devolver el último elemento
let ultimo = numeros.pop(); // Some(50)
println!("Último elemento: {:?}", ultimo);
println!("Vector después de pop: {:?}", numeros); // [10, 20, 30, 40]
// Eliminar elemento en una posición específica
let elemento_eliminado = numeros.remove(1); // 20
println!("Elemento eliminado: {}", elemento_eliminado);
println!("Vector después de remove: {:?}", numeros); // [10, 30, 40]
El método drain_filter
permite eliminar elementos que cumplen cierta condición:
let mut numeros = vec![1, 2, 3, 4, 5, 6];
// Eliminar números pares
let pares: Vec<_> = numeros.drain_filter(|x| x % 2 == 0).collect();
println!("Números pares eliminados: {:?}", pares); // [2, 4, 6]
println!("Vector resultante: {:?}", numeros); // [1, 3, 5]
Iteración sobre vectores
Podemos recorrer los elementos de un vector de varias formas:
let animales = vec!["perro", "gato", "conejo"];
// Iteración básica por referencia
for animal in &animales {
println!("{}", animal);
}
// Iteración con índices
for (indice, animal) in animales.iter().enumerate() {
println!("Animal {}: {}", indice, animal);
}
// Iteración con mutabilidad
let mut puntuaciones = vec![85, 92, 78];
for puntuacion in &mut puntuaciones {
*puntuacion += 5; // Añadir 5 puntos a cada puntuación
}
println!("Puntuaciones ajustadas: {:?}", puntuaciones); // [90, 97, 83]
Métodos útiles
Los vectores en Rust incluyen numerosos métodos que facilitan operaciones comunes:
let mut valores = vec![3, 1, 4, 1, 5, 9, 2, 6];
// Ordenar el vector
valores.sort();
println!("Ordenado: {:?}", valores); // [1, 1, 2, 3, 4, 5, 6, 9]
// Eliminar duplicados (primero debe estar ordenado)
valores.dedup();
println!("Sin duplicados: {:?}", valores); // [1, 2, 3, 4, 5, 6, 9]
// Verificar si contiene un valor
let contiene_cinco = valores.contains(&5);
println!("¿Contiene el 5? {}", contiene_cinco); // true
// Encontrar la posición de un elemento
if let Some(pos) = valores.iter().position(|&x| x == 3) {
println!("El 3 está en la posición {}", pos);
}
// Dividir un vector
let mut numeros = vec![1, 2, 3, 4, 5];
let parte = numeros.split_off(3); // Divide desde el índice 3
println!("Primera parte: {:?}", numeros); // [1, 2, 3]
println!("Segunda parte: {:?}", parte); // [4, 5]
Capacidad y rendimiento
Los vectores gestionan automáticamente su memoria, pero podemos optimizar su rendimiento:
// Crear un vector con capacidad inicial
let mut datos = Vec::with_capacity(1000);
// Añadir elementos no causará realocaciones hasta superar la capacidad
for i in 0..100 {
datos.push(i);
}
println!("Longitud: {}", datos.len()); // 100
println!("Capacidad: {}", datos.capacity()); // 1000
// Reducir la capacidad para ajustarla al tamaño actual
datos.shrink_to_fit();
println!("Capacidad después de shrink_to_fit: {}", datos.capacity()); // 100
La capacidad es el espacio reservado en memoria, mientras que la longitud es el número de elementos. Cuando añadimos elementos y superamos la capacidad, Rust automáticamente reserva más memoria (típicamente duplicando la capacidad actual).
Conversiones con arrays y slices
Los vectores se pueden convertir fácilmente desde y hacia arrays y slices:
// De array a vector
let array = [1, 2, 3, 4];
let vector: Vec<i32> = array.to_vec();
// O alternativamente:
let vector = Vec::from(array);
// De slice a vector
let slice = &[5, 6, 7];
let vector = slice.to_vec();
// De vector a slice
let vector = vec![8, 9, 10];
let slice = &vector[..]; // Slice que abarca todo el vector
let slice_parcial = &vector[1..]; // Slice desde el índice 1 hasta el final
Es importante recordar que insertar elementos en colecciones puede transferir su propiedad, algo que estudiaremos en el módulo de ownership.
HashMap y BTreeMap
Los mapas son estructuras de datos que almacenan pares clave-valor, permitiendo recuperar valores rápidamente a partir de sus claves. En Rust, las implementaciones más comunes son HashMap<K, V>
y BTreeMap<K, V>
, donde K
representa el tipo de la clave y V
el tipo del valor.
Estas colecciones son fundamentales cuando necesitamos asociar datos relacionados y acceder a ellos de forma eficiente. Por ejemplo, podríamos usar un mapa para almacenar puntuaciones de jugadores, donde el nombre del jugador es la clave y su puntuación el valor.
HashMap: mapas basados en hash
HashMap<K, V>
implementa un mapa utilizando una tabla hash interna. Esta estructura ofrece operaciones de búsqueda, inserción y eliminación con un rendimiento promedio de O(1) (tiempo constante), lo que la hace extremadamente eficiente para la mayoría de los casos de uso.
Para usar HashMap
, primero debemos importarlo:
use std::collections::HashMap;
// Crear un HashMap vacío que asocia cadenas con enteros
let mut puntuaciones: HashMap<String, i32> = HashMap::new();
Inserción de elementos
Podemos añadir pares clave-valor usando el método insert
:
let mut inventario = HashMap::new();
// Añadir elementos (producto -> cantidad)
inventario.insert("manzanas", 5);
inventario.insert("plátanos", 8);
inventario.insert("naranjas", 12);
// Sobrescribir un valor existente
inventario.insert("manzanas", 7); // Ahora tenemos 7 manzanas, no 5
También podemos insertar un valor solo si la clave no existe:
// Insertar solo si la clave no existe
inventario.entry("peras").or_insert(3);
// Si la clave ya existe, podemos modificar su valor
*inventario.entry("plátanos").or_insert(0) += 2; // Añade 2 plátanos más
Acceso a valores
Hay varias formas de acceder a los valores de un HashMap
:
let mut capitales = HashMap::new();
capitales.insert("España", "Madrid");
capitales.insert("Francia", "París");
capitales.insert("Italia", "Roma");
// Acceso seguro con get (devuelve Option<&V>)
match capitales.get("España") {
Some(capital) => println!("La capital de España es {}", capital),
None => println!("No conozco la capital de ese país"),
}
// Acceso con valor por defecto
let capital_portugal = capitales.get("Portugal").unwrap_or(&"Desconocida");
println!("La capital de Portugal es {}", capital_portugal);
// Verificar si existe una clave
if capitales.contains_key("Italia") {
println!("Tenemos información sobre Italia");
}
Eliminación de elementos
Podemos eliminar entradas de un HashMap
de varias maneras:
let mut edades = HashMap::new();
edades.insert("Ana", 28);
edades.insert("Carlos", 32);
edades.insert("Elena", 25);
// Eliminar una entrada específica
let edad_eliminada = edades.remove("Carlos");
println!("Edad eliminada: {:?}", edad_eliminada); // Some(32)
// Eliminar entradas que cumplan cierta condición
let mayores_eliminados: HashMap<_, _> = edades
.drain_filter(|_, edad| *edad > 26)
.collect();
println!("Personas mayores de 26 eliminadas: {:?}", mayores_eliminados);
println!("Edades restantes: {:?}", edades);
Iteración sobre un HashMap
Podemos recorrer todas las entradas, claves o valores:
let mut población = HashMap::new();
población.insert("Madrid", 3_223_000);
población.insert("Barcelona", 1_620_000);
población.insert("Valencia", 791_000);
// Iterar sobre pares clave-valor
for (ciudad, habitantes) in &población {
println!("{} tiene {} habitantes", ciudad, habitantes);
}
// Iterar solo sobre las claves
for ciudad in población.keys() {
println!("Ciudad: {}", ciudad);
}
// Iterar solo sobre los valores
let total: i32 = población.values().sum();
println!("Población total: {}", total);
BTreeMap: mapas ordenados
BTreeMap<K, V>
implementa un mapa utilizando un árbol B como estructura interna. A diferencia de HashMap
, mantiene las claves ordenadas según su orden natural, lo que permite operaciones adicionales como obtener rangos de claves.
Las operaciones en un BTreeMap
tienen un rendimiento de O(log n), algo más lento que HashMap
pero aún muy eficiente.
use std::collections::BTreeMap;
let mut calificaciones = BTreeMap::new();
calificaciones.insert("Matemáticas", 85);
calificaciones.insert("Historia", 92);
calificaciones.insert("Ciencias", 78);
La principal ventaja de BTreeMap
es que las claves siempre están ordenadas:
// Las claves se imprimen en orden alfabético: Ciencias, Historia, Matemáticas
for (asignatura, nota) in &calificaciones {
println!("{}: {}", asignatura, nota);
}
Operaciones específicas de BTreeMap
BTreeMap
ofrece métodos para trabajar con rangos ordenados:
let mut ranking = BTreeMap::new();
ranking.insert(1, "Alicia");
ranking.insert(5, "Carlos");
ranking.insert(2, "Berta");
ranking.insert(4, "David");
ranking.insert(3, "Elena");
// Obtener un rango de entradas
let top3 = ranking.range(1..=3);
println!("Top 3 jugadores:");
for (posición, nombre) in top3 {
println!("{}. {}", posición, nombre);
}
// Obtener la primera y última entrada
if let Some((primera_pos, primer_nombre)) = ranking.first_key_value() {
println!("Primer lugar: {}. {}", primera_pos, primer_nombre);
}
if let Some((última_pos, último_nombre)) = ranking.last_key_value() {
println!("Último lugar: {}. {}", última_pos, último_nombre);
}
Comparación entre HashMap y BTreeMap
Elegir entre HashMap
y BTreeMap
depende de tus necesidades específicas:
HashMap:
Ventajas: Operaciones más rápidas en promedio (O(1))
Desventajas: No mantiene las claves ordenadas
Uso ideal: Cuando necesitas máxima velocidad y no te importa el orden
BTreeMap:
Ventajas: Claves siempre ordenadas, permite operaciones de rango
Desventajas: Operaciones ligeramente más lentas (O(log n))
Uso ideal: Cuando necesitas mantener las claves ordenadas o realizar operaciones por rangos
Casos de uso prácticos
Contador de frecuencias con HashMap
let texto = "rust es un lenguaje de programación rust es seguro";
let mut frecuencias = HashMap::new();
for palabra in texto.split_whitespace() {
*frecuencias.entry(palabra).or_insert(0) += 1;
}
println!("Frecuencia de palabras:");
for (palabra, frecuencia) in &frecuencias {
println!("{}: {}", palabra, frecuencia);
}
Agenda telefónica ordenada con BTreeMap
let mut agenda = BTreeMap::new();
agenda.insert("Ana García", "612345678");
agenda.insert("Carlos López", "623456789");
agenda.insert("Beatriz Martín", "634567890");
println!("Contactos (ordenados alfabéticamente):");
for (nombre, teléfono) in &agenda {
println!("{}: {}", nombre, teléfono);
}
Combinando ambos tipos de mapas
A veces, podemos necesitar convertir entre ambos tipos:
use std::collections::{HashMap, BTreeMap};
// Crear un HashMap
let mut datos_desordenados = HashMap::new();
datos_desordenados.insert("c", 3);
datos_desordenados.insert("a", 1);
datos_desordenados.insert("b", 2);
// Convertir a BTreeMap para obtener los datos ordenados
let datos_ordenados: BTreeMap<_, _> = datos_desordenados.into_iter().collect();
println!("Datos ordenados:");
for (clave, valor) in &datos_ordenados {
println!("{}: {}", clave, valor);
}
Es importante recordar que insertar elementos en colecciones puede transferir su propiedad, algo que estudiaremos en el módulo de ownership.
HashSet y BTreeSet
Los conjuntos (sets) son colecciones que almacenan elementos únicos sin un orden específico. En Rust, disponemos de dos implementaciones principales: HashSet<T>
y BTreeSet<T>
, donde T
representa el tipo de los elementos almacenados.
A diferencia de los vectores que permiten elementos duplicados, los conjuntos garantizan que cada elemento aparezca una sola vez. Esta característica los hace ideales para operaciones como eliminar duplicados, comprobar pertenencia o realizar operaciones matemáticas de conjuntos.
HashSet: conjuntos basados en hash
HashSet<T>
implementa un conjunto utilizando una tabla hash interna (similar a HashMap
), lo que proporciona operaciones de búsqueda, inserción y eliminación con un rendimiento promedio de O(1).
Para utilizar HashSet
, primero debemos importarlo:
use std::collections::HashSet;
// Crear un HashSet vacío de enteros
let mut numeros: HashSet<i32> = HashSet::new();
Creación e inserción de elementos
Podemos crear conjuntos de varias formas:
// Conjunto vacío
let mut frutas = HashSet::new();
// Añadir elementos individuales
frutas.insert("manzana");
frutas.insert("naranja");
frutas.insert("plátano");
// Intentar insertar un elemento duplicado
let insertado = frutas.insert("manzana");
println!("¿Se insertó el duplicado? {}", insertado); // false, ya existía
// Crear un conjunto a partir de un iterador
let vocales: HashSet<char> = "aeiou".chars().collect();
println!("Vocales: {:?}", vocales);
Verificación de elementos
Una de las operaciones más comunes con conjuntos es comprobar si contienen cierto elemento:
let colores = HashSet::from(["rojo", "verde", "azul"]);
// Verificar si un elemento existe
if colores.contains("verde") {
println!("El verde está en la lista de colores");
}
// Comprobar si está vacío
if !colores.is_empty() {
println!("Tenemos {} colores", colores.len());
}
Eliminación de elementos
Podemos eliminar elementos de un HashSet
de varias maneras:
let mut lenguajes = HashSet::new();
lenguajes.insert("Rust");
lenguajes.insert("Python");
lenguajes.insert("JavaScript");
lenguajes.insert("C++");
// Eliminar un elemento específico
let eliminado = lenguajes.remove("Python");
println!("¿Se eliminó Python? {}", eliminado); // true
// Eliminar elementos que cumplan cierta condición
let eliminados: HashSet<_> = lenguajes
.drain_filter(|lang| lang.len() > 4)
.collect();
println!("Lenguajes con más de 4 letras: {:?}", eliminados);
println!("Lenguajes restantes: {:?}", lenguajes);
Operaciones matemáticas de conjuntos
Los conjuntos en Rust permiten realizar operaciones matemáticas como unión, intersección y diferencia:
let grupo_a: HashSet<_> = [1, 2, 3, 4].iter().cloned().collect();
let grupo_b: HashSet<_> = [3, 4, 5, 6].iter().cloned().collect();
// Unión: elementos que están en A o en B (o en ambos)
let union: HashSet<_> = grupo_a.union(&grupo_b).cloned().collect();
println!("Unión: {:?}", union); // {1, 2, 3, 4, 5, 6}
// Intersección: elementos que están tanto en A como en B
let interseccion: HashSet<_> = grupo_a.intersection(&grupo_b).cloned().collect();
println!("Intersección: {:?}", interseccion); // {3, 4}
// Diferencia: elementos en A pero no en B
let diferencia: HashSet<_> = grupo_a.difference(&grupo_b).cloned().collect();
println!("Diferencia A-B: {:?}", diferencia); // {1, 2}
// Diferencia simétrica: elementos en A o B, pero no en ambos
let dif_simetrica: HashSet<_> = grupo_a.symmetric_difference(&grupo_b).cloned().collect();
println!("Diferencia simétrica: {:?}", dif_simetrica); // {1, 2, 5, 6}
Verificación de subconjuntos y superconjuntos
Podemos comprobar relaciones entre conjuntos:
let numeros = HashSet::from([1, 2, 3, 4, 5]);
let pares = HashSet::from([2, 4]);
let impares = HashSet::from([1, 3, 5]);
let primos = HashSet::from([2, 3, 5, 7]);
// Verificar si un conjunto es subconjunto de otro
println!("¿Pares es subconjunto de números? {}", pares.is_subset(&numeros)); // true
// Verificar si un conjunto es superconjunto de otro
println!("¿Números es superconjunto de impares? {}", numeros.is_superset(&impares)); // true
// Verificar si dos conjuntos son disjuntos (no tienen elementos en común)
println!("¿Pares e impares son disjuntos? {}", pares.is_disjoint(&impares)); // true
println!("¿Impares y primos son disjuntos? {}", impares.is_disjoint(&primos)); // false
BTreeSet: conjuntos ordenados
BTreeSet<T>
implementa un conjunto utilizando un árbol B como estructura interna. A diferencia de HashSet
, mantiene los elementos ordenados según su orden natural, lo que permite operaciones adicionales como obtener rangos de elementos.
use std::collections::BTreeSet;
let mut calificaciones = BTreeSet::new();
calificaciones.insert(85);
calificaciones.insert(92);
calificaciones.insert(78);
calificaciones.insert(95);
La principal ventaja de BTreeSet
es que los elementos siempre están ordenados:
// Los elementos se imprimen en orden ascendente: 78, 85, 92, 95
println!("Calificaciones ordenadas:");
for nota in &calificaciones {
println!("{}", nota);
}
// Obtener la calificación más baja y más alta
if let Some(minima) = calificaciones.first() {
println!("Calificación más baja: {}", minima);
}
if let Some(maxima) = calificaciones.last() {
println!("Calificación más alta: {}", maxima);
}
Operaciones específicas de BTreeSet
BTreeSet
ofrece métodos para trabajar con rangos ordenados:
let numeros = BTreeSet::from([10, 20, 30, 40, 50, 60, 70]);
// Obtener un rango de elementos
println!("Números entre 25 y 55:");
for n in numeros.range(25..=55) {
println!("{}", n); // Imprime 30, 40, 50
}
// Obtener elementos mayores o iguales a un valor
println!("Números mayores o iguales a 50:");
for n in numeros.range(50..) {
println!("{}", n); // Imprime 50, 60, 70
}
// Obtener elementos menores que un valor
println!("Números menores que 40:");
for n in numeros.range(..40) {
println!("{}", n); // Imprime 10, 20, 30
}
Operaciones de división (split)
BTreeSet
permite dividir un conjunto en dos partes:
let mut letras = BTreeSet::from(['a', 'b', 'c', 'd', 'e', 'f']);
// Dividir el conjunto en dos partes: <= 'c' y > 'c'
let segunda_mitad = letras.split_off(&'c');
println!("Primera mitad: {:?}", letras); // {'a', 'b', 'c'}
println!("Segunda mitad: {:?}", segunda_mitad); // {'d', 'e', 'f'}
Comparación entre HashSet y BTreeSet
Elegir entre HashSet
y BTreeSet
depende de tus necesidades específicas:
HashSet:
Ventajas: Operaciones más rápidas en promedio (O(1))
Desventajas: No mantiene los elementos ordenados
Uso ideal: Cuando necesitas máxima velocidad y no te importa el orden
BTreeSet:
Ventajas: Elementos siempre ordenados, permite operaciones de rango
Desventajas: Operaciones ligeramente más lentas (O(log n))
Uso ideal: Cuando necesitas mantener los elementos ordenados o realizar operaciones por rangos
Casos de uso prácticos
Eliminación de duplicados con HashSet
let texto = "a b c a d e f c";
let palabras: Vec<&str> = texto.split_whitespace().collect();
// Convertir a HashSet para eliminar duplicados
let palabras_unicas: HashSet<_> = palabras.iter().cloned().collect();
println!("Palabras únicas: {:?}", palabras_unicas);
// Volver a convertir a vector si es necesario
let palabras_sin_duplicados: Vec<_> = palabras_unicas.into_iter().collect();
println!("Vector sin duplicados: {:?}", palabras_sin_duplicados);
Filtrado de elementos únicos
fn obtener_elementos_unicos(lista1: &[i32], lista2: &[i32]) -> Vec<i32> {
let conjunto1: HashSet<_> = lista1.iter().cloned().collect();
let conjunto2: HashSet<_> = lista2.iter().cloned().collect();
// Elementos que están en lista1 pero no en lista2
conjunto1.difference(&conjunto2).cloned().collect()
}
let resultados_grupo_a = [85, 90, 74, 83, 92];
let resultados_grupo_b = [90, 72, 85, 64, 88];
let unicos_grupo_a = obtener_elementos_unicos(&resultados_grupo_a, &resultados_grupo_b);
println!("Resultados únicos del grupo A: {:?}", unicos_grupo_a);
Registro de accesos ordenado con BTreeSet
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Acceso {
timestamp: u64,
usuario: String,
}
let mut registro = BTreeSet::new();
// Registrar accesos (no necesariamente en orden)
registro.insert(Acceso { timestamp: 1623456789, usuario: "usuario1".to_string() });
registro.insert(Acceso { timestamp: 1623456123, usuario: "usuario2".to_string() });
registro.insert(Acceso { timestamp: 1623457890, usuario: "usuario3".to_string() });
// Los accesos se mostrarán ordenados por timestamp (y luego por usuario si hay empate)
println!("Registro de accesos ordenado:");
for acceso in ®istro {
println!("{}: {}", acceso.timestamp, acceso.usuario);
}
Es importante recordar que insertar elementos en colecciones puede transferir su propiedad, algo que estudiaremos en el módulo de ownership.
Otras lecciones de Rust
Accede a todas las lecciones de Rust y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Rust
Introducción Y Entorno
Primer Programa
Introducción Y Entorno
Instalación Del Entorno
Introducción Y Entorno
Funciones
Sintaxis
Operadores
Sintaxis
Estructuras De Control Condicional
Sintaxis
Arrays Y Strings
Sintaxis
Manejo De Errores Panic
Sintaxis
Variables Y Tipos Básicos
Sintaxis
Estructuras De Control Iterativo
Sintaxis
Colecciones Estándar
Estructuras De Datos
Option Y Result
Estructuras De Datos
Pattern Matching
Estructuras De Datos
Estructuras (Structs)
Estructuras De Datos
Enumeraciones Enums
Estructuras De Datos
El Concepto De Ownership
Ownership
Lifetimes Básicos
Ownership
Slices Y Referencias Parciales
Ownership
References Y Borrowing
Ownership
Funciones Anónimas Closures
Abstracción
Traits De La Biblioteca Estándar
Abstracción
Traits
Abstracción
Generics
Abstracción
Channels Y Paso De Mensajes
Concurrencia
Memoria Compartida Segura
Concurrencia
Threads Y Sincronización Básica
Concurrencia
Introducción A Tokio
Asincronía
Fundamentos Asíncronos Y Futures
Asincronía
Async/await
Asincronía
Ejercicios de programación de Rust
Evalúa tus conocimientos de esta lección Colecciones estándar con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la estructura y uso de vectores (
Vec<T>
) en Rust, incluyendo creación, acceso, modificación e iteración. - Aprender a utilizar mapas (
HashMap
yBTreeMap
) para almacenar pares clave-valor, con sus diferencias y casos de uso. - Conocer los conjuntos (
HashSet
yBTreeSet
), sus propiedades de unicidad y operaciones matemáticas de conjuntos. - Diferenciar entre las implementaciones basadas en hash y en árboles B, entendiendo sus ventajas y desventajas.
- Aplicar las colecciones estándar en ejemplos prácticos para resolver problemas comunes de programación.