💻 Exemplos: Capítulo 13: Generics Avançados, Wildcards Delimitados, e Coleções Set e Map
Especialização em Sistemas com Java 21 LTS • Capítulo 13
🎯 Visão Geral dos Exemplos Práticos
Neste laboratório prático, implementaremos exemplos corporativos completos explorando:
- Cache LRU (Least Recently Used) com
LinkedHashMap: política de despejo automático de entradas expiradas baseada na ordem de acesso. - Índice Ordenado com
TreeMape Navegação Range: busca eficiente de faixas de valores (subMap,tailMap,headMap). - Mecanismo Genérico de Transferência com PECS: métodos utilitários aplicando covariância (
? extends T) e contravariância (? super T).
💻 Exemplo 01 — Cache LRU de Sessões e Catálogo com TreeMap
package com.empresa.colecoes;
import java.math.BigDecimal;
import java.util.*;
/**
* Cache de alta performance e índice ordenado em árvore balanceada.
*/
public class SistemaCacheEIndices {
public record SessaoUsuario(String usuario, String ip, long timestampLogin) {}
public record AtivoFinanceiro(String ticker, BigDecimal cotacao) implements Comparable<AtivoFinanceiro> {
@Override
public int compareTo(AtivoFinanceiro outro) {
return this.ticker.compareTo(outro.ticker);
}
}
// Cache LRU que expulsa automaticamente as entradas menos recentemente acessadas
public static class CacheLruSessoes<K, V> extends LinkedHashMap<K, V> {
private final int maxEntradas;
public CacheLruSessoes(int maxEntradas) {
super(maxEntradas, 0.75f, true); // true = access-order
this.maxEntradas = maxEntradas;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
boolean deveRemover = size() > maxEntradas;
if (deveRemover) {
System.out.printf(" [CACHE EVICTION] Expulsando chave expirada: %s%n", eldest.getKey());
}
return deveRemover;
}
}
public static void main(String[] args) {
System.out.println("================================================================================");
System.out.println(" CACHE LRU E ÍNDICES EM ÁRVORE RUBRO-NEGRA (JAVA 21) ");
System.out.println("================================================================================");
// 1. Teste de Cache LRU
System.out.println("--- 1. Demonstração de Evicção do Cache LRU (Limite 3) ---");
CacheLruSessoes<String, SessaoUsuario> cache = new CacheLruSessoes<>(3);
cache.put("SESS-01", new SessaoUsuario("admin", "192.168.1.10", System.currentTimeMillis()));
cache.put("SESS-02", new SessaoUsuario("financeiro", "192.168.1.15", System.currentTimeMillis()));
cache.put("SESS-03", new SessaoUsuario("suporte", "192.168.1.20", System.currentTimeMillis()));
System.out.println("Sessões no cache: " + cache.keySet());
// Acessamos SESS-01 -> Torna-se o mais recentemente usado
System.out.println("Acessando SESS-01...");
cache.get("SESS-01");
// Inserimos SESS-04 -> Deve expulsar SESS-02 (o mais antigo sem acesso)
System.out.println("Inserindo SESS-04...");
cache.put("SESS-04", new SessaoUsuario("auditoria", "192.168.1.50", System.currentTimeMillis()));
System.out.println("Sessões sobreviventes no cache: " + cache.keySet());
// 2. Teste de TreeMap com Navegação Range
System.out.println("\n--- 2. Livro de Ofertas e Índices com TreeMap (O(log n)) ---");
NavigableMap<String, AtivoFinanceiro> livroOfertas = new TreeMap<>();
livroOfertas.put("PETR4", new AtivoFinanceiro("PETR4", new BigDecimal("37.80")));
livroOfertas.put("VALE3", new AtivoFinanceiro("VALE3", new BigDecimal("62.40")));
livroOfertas.put("ITUB4", new AtivoFinanceiro("ITUB4", new BigDecimal("33.15")));
livroOfertas.put("BBDC4", new AtivoFinanceiro("BBDC4", new BigDecimal("14.50")));
livroOfertas.put("WEGE3", new AtivoFinanceiro("WEGE3", new BigDecimal("51.20")));
System.out.println("Ativos ordenados lexicograficamente:");
livroOfertas.forEach((ticker, ativo) ->
System.out.printf(" Ticker: %-6s | Cotação: R$ %6.2f%n", ticker, ativo.cotacao()));
// Intervalo de mercado (Range Query de ITUB4 até PETR4)
System.out.println("\nSub-mapa no intervalo [ITUB4 até PETR4]:");
SortedMap<String, AtivoFinanceiro> subMapa = livroOfertas.subMap("ITUB4", "PETR4\0");
subMapa.forEach((ticker, ativo) ->
System.out.printf(" ➡️ %-6s : R$ %6.2f%n", ticker, ativo.cotacao()));
System.out.println("================================================================================");
}
}
💻 Exemplo 02 — Implementação Rigorosa do Princípio PECS
package com.empresa.colecoes;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* Utilitário genérico de processamento com covariância e contravariância.
*/
public class ProcessadorColecoesPecs {
public static abstract class Transacao {
private final String id;
private final BigDecimal valor;
public Transacao(String id, BigDecimal valor) { this.id = id; this.valor = valor; }
public String getId() { return id; }
public BigDecimal getValor() { return valor; }
}
public static class PixTransacao extends Transacao {
public PixTransacao(String id, BigDecimal valor) { super(id, valor); }
}
public static class TedTransacao extends Transacao {
public TedTransacao(String id, BigDecimal valor) { super(id, valor); }
}
// PECS: Origem é PRODUTORA (extends) e Destino é CONSUMIDORA (super)
public static <T extends Transacao> void transferirLote(
List<? extends T> produtor,
List<? super T> consumidor) {
for (T elemento : produtor) {
consumidor.add(elemento); // Consumidor recebe elementos com segurança
}
}
public static void main(String[] args) {
List<PixTransacao> lotePix = List.of(
new PixTransacao("PIX-1", new BigDecimal("100.00")),
new PixTransacao("PIX-2", new BigDecimal("250.00"))
);
List<Transacao> ledgerGeral = new ArrayList<>();
transferirLote(lotePix, ledgerGeral); // Compila com perfeição graças a PECS!
System.out.println("Itens consolidados no ledger geral:");
for (Transacao tx : ledgerGeral) {
System.out.printf(" TX ID: %s | Valor: R$ %.2f%n", tx.getId(), tx.getValor());
}
}
}
📋 Resultado Esperado no Console
================================================================================
CACHE LRU E ÍNDICES EM ÁRVORE RUBRO-NEGRA (JAVA 21)
================================================================================
--- 1. Demonstração de Evicção do Cache LRU (Limite 3) ---
Sessões no cache: [SESS-01, SESS-02, SESS-03]
Acessando SESS-01...
Inserindo SESS-04...
[CACHE EVICTION] Expulsando chave expirada: SESS-02
Sessões sobreviventes no cache: [SESS-03, SESS-01, SESS-04]
--- 2. Livro de Ofertas e Índices com TreeMap (O(log n)) ---
Ativos ordenados lexicograficamente:
Ticker: BBDC4 | Cotação: R$ 14.50
Ticker: ITUB4 | Cotação: R$ 33.15
Ticker: PETR4 | Cotação: R$ 37.80
Ticker: VALE3 | Cotação: R$ 62.40
Ticker: WEGE3 | Cotação: R$ 51.20
Sub-mapa no intervalo [ITUB4 até PETR4]:
➡️ ITUB4 : R$ 33.15
➡️ PETR4 : R$ 37.80
================================================================================
Itens consolidados no ledger geral:
TX ID: PIX-1 | Valor: R$ 100.00
TX ID: PIX-2 | Valor: R$ 250.00