💻 Exemplos: Capítulo 12: Coleções da Biblioteca Padrão e Iteradores

Especialização em Sistemas com Rust • Demonstrações Práticas Compiláveis


🎯 Objetivo dos Exemplos

Dominar as coleções fundamentais da biblioteca padrão do Rust (std::collections::HashMap, HashSet e Vec), a API declarativa de Iteradores com avaliação preguiçosa (lazy), mutação atômica de mapas com o padrão Entry API (.or_insert()) e combinadores funcionais (map, filter, fold, collect).


1. Código Fonte Completo (src/main.rs)

//! Coleções Padrão, Entry API e Programação Funcional com Iteradores em Rust

use std::collections::{HashMap, HashSet};

#[derive(Debug, PartialEq, Eq, Hash)]
struct RegistroEvento {
    servico: String,
    codigo_http: u16,
}

fn main() {
    println!("=== COLEÇÕES PADRÃO E ITERADORES IDIOMÁTICOS ===");

    // 1. Tabela Hash (HashMap) e o Idioma Entry API
    println!("Contabilizando ocorrências de logs com HashMap e Entry API:");
    let logs_recebidos = vec![
        "AUTH_SUCCESS", "DB_TIMEOUT", "AUTH_SUCCESS",
        "API_NOT_FOUND", "DB_TIMEOUT", "DB_TIMEOUT",
    ];

    let mut contador_ocorrencias: HashMap<&str, u32> = HashMap::new();

    for log in logs_recebidos {
        // .entry(chave).or_insert(0) obtém uma referência mutável ao valor existente
        // ou insere 0 caso não exista, permitindo incremento direto em uma única linha!
        let contador = contador_ocorrencias.entry(log).or_insert(0);
        *contador += 1;
    }

    for (tipo_log, contagem) in &contador_ocorrencias {
        println!("  Log: {:<15} | Total de Ocorrências: {}", tipo_log, contagem);
    }

    // 2. Conjuntos Únicos com HashSet
    println!("\nFiltrando IPs únicos de conexões suspeitas com HashSet:");
    let acessos_brutos = vec![
        "192.168.1.10", "10.0.0.5", "192.168.1.10",
        "172.16.0.1", "10.0.0.5", "192.168.1.10",
    ];

    let ips_unicos: HashSet<&str> = acessos_brutos.into_iter().collect();
    println!("IPs únicos detectados (total {}): {:?}", ips_unicos.len(), ips_unicos);

    // 3. Pipeline Funcional de Iteradores (Zero-Cost Abstractions)
    println!("\nProcessando métricas de latência com adaptadores de iterador:");
    let latencias_ms = vec![12, 45, 180, 22, 95, 310, 8, 140];

    // Operações encadeadas são preguiçosas: nenhum processamento ocorre até o .collect() ou .fold()
    let soma_latencias_criticas: u32 = latencias_ms
        .iter()
        .filter(|&&lat| lat > 50)          // Filtra apenas requisições lentas (> 50ms)
        .map(|&lat| lat * 2)               // Aplica peso de penalidade dobrado
        .fold(0, |acumulador, lat| acumulador + lat); // Reduz somando todos

    println!("Soma ponderada das latências críticas (> 50ms * 2): {} ms", soma_latencias_criticas);

    // 4. Criação de Vetor Filtrado e Mapeado com .collect()
    let alertas_formatados: Vec<String> = latencias_ms
        .iter()
        .filter(|&&lat| lat > 100)
        .map(|&lat| format!("ALERTA_LATENCIA_{}MS", lat))
        .collect();

    println!("Alertas gerados: {:?}", alertas_formatados);

    // 5. Mutação de Coleção in-place com iter_mut()
    let mut niveis_buffer = vec![100, 200, 300];
    println!("\nValores antes de iter_mut(): {:?}", niveis_buffer);
    for nivel in niveis_buffer.iter_mut() {
        *nivel += 50; // Desreferenciação e mutação direta
    }
    println!("Valores após iter_mut(): {:?}", niveis_buffer);
}

2. Saída Esperada no Terminal

=== COLEÇÕES PADRÃO E ITERADORES IDIOMÁTICOS ===
Contabilizando ocorrências de logs com HashMap e Entry API:
  Log: AUTH_SUCCESS    | Total de Ocorrências: 2
  Log: API_NOT_FOUND   | Total de Ocorrências: 1
  Log: DB_TIMEOUT      | Total de Ocorrências: 3

Filtrando IPs únicos de conexões suspeitas com HashSet:
IPs únicos detectados (total 3): {"172.16.0.1", "10.0.0.5", "192.168.1.10"}

Processando métricas de latência com adaptadores de iterador:
Soma ponderada das latências críticas (> 50ms * 2): 1450 ms
Alertas gerados: ["ALERTA_LATENCIA_180MS", "ALERTA_LATENCIA_310MS", "ALERTA_LATENCIA_140MS"]

Valores antes de iter_mut(): [100, 200, 300]
Valores após iter_mut(): [150, 250, 350]