Estruturas de Dados Coletoras em Java: List, Set e Map

Interface List e suas Implementações

A interface List é uma subinterface de Collection projetada para manter uma sequência ordenada de elementos. Diferente de outras coleções, ela preserva a ordem de inserção, permite duplicatas e fornece acesso direto via índice. As principais implementações são ArrayList, LinkedList e Vector.

ArrayList: Baseado em Vetores Dinâmicos

O ArrayList utiliza uma estrutura de array internamente. Isso garante consultas rápidas por índice, mas torna a inserção e remoção no meio da estrutura mais custosa. Ele não é thread-safe, o que resulta em maior desempenho em ambientes de thread única.

  • O array inicial é alocado apenas na primeira adição de elemento, não no momento da instanciação.
  • Quando a capacidade máxima é atingida, o array é redimensionado automaticamente usando Arrays.copyOf().
  • O fator de expansão padrão é de 1,5 vezes o tamanho atual.
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class GerenciadorSequencial {
    public static void main(String[] args) {
        List<string> repositorio = new ArrayList<>();

        repositorio.add("TecnologiaA");
        repositorio.add("TecnologiaB");
        repositorio.add("TecnologiaC");
        repositorio.add("TecnologiaB"); // Permite duplicatas

        System.out.println("Conteúdo inicial: " + repositorio);

        // Inserção em índice específico
        repositorio.add(2, "TecnologiaD");
        System.out.println("Após inserção no índice 2: " + repositorio);

        // Recuperação e substituição
        String elementoResgatado = repositorio.get(1);
        System.out.println("Elemento no índice 1: " + elementoResgatado);

        repositorio.set(1, "TecnologiaAtualizada");
        System.out.println("Após substituição: " + repositorio);

        // Iteração bidirecional
        ListIterator<string> iteradorSeq = repositorio.listIterator();
        while (iteradorSeq.hasNext()) {
            System.out.print(iteradorSeq.next() + " ");
        }
        System.out.println("\n--- Ordem inversa ---");
        while (iteradorSeq.hasPrevious()) {
            System.out.print(iteradorSeq.previous() + " ");
        }
    }
}</string></string>

LinkedList: Lista Duplamente Encadeada

A LinkedList utiliza nós conectados entre si, permitindo adições e remoções eficientes nas extremidades. Embora possua métodos de acesso por índice, a navegação sequencial é mais performática. Oferece métodos dedicados para operações de pilha (stack) e fila (queue).

import java.util.LinkedList;

public class OperacoesListaEncadeada {
    public static void main(String[] args) {
        LinkedList<string> filaProcessos = new LinkedList<>();

        filaProcessos.add("ProcessoX");
        filaProcessos.add("ProcessoY");
        filaProcessos.add("ProcessoZ");

        // Operações nas extremidades
        filaProcessos.addFirst("ProcessoInicio");
        filaProcessos.addLast("ProcessoFim");

        System.out.println("Primeiro: " + filaProcessos.peekFirst());
        System.out.println("Último: " + filaProcessos.peekLast());

        System.out.println("Removendo primeiro: " + filaProcessos.removeFirst());
        System.out.println("Removendo último: " + filaProcessos.removeLast());
        System.out.println("Estado final: " + filaProcessos);
    }
}</string>

Simulando uma Pilha com LinkedList

Abaixo, uma implementação encapsulada que expõe comportamento LIFO (Last In, First Out):

import java.util.LinkedList;

public class PilhaGenerica {
    private LinkedList<object> armazenamento;

    public PilhaGenerica() {
        armazenamento = new LinkedList<>();
    }

    public void empilhar(Object item) {
        armazenamento.addFirst(item);
    }

    public Object desempilhar() {
        if (armazenamento.isEmpty()) {
            throw new IllegalStateException("A pilha está vazia.");
        }
        return armazenamento.removeFirst();
    }

    public int capacidadeAtual() {
        return armazenamento.size();
    }

    @Override
    public String toString() {
        return "Pilha[conteudo=" + armazenamento + "]";
    }
}</object>

Vector: Legado Sincronizado

O Vector funciona de maneira similar ao ArrayList, mas suas operações são protegidas por synchronized. Devido à sobrecarga de thread safety, é desencorajado em aplicações modernas, sendo substituído por Collections.synchronizedList() ou CopyOnWriteArrayList.

Interface Set: Elementos Únicos

A interface Set proíbe duplicatas e não garante ordem de iteração (exceto implementações específicas). As principais variações são HashSet e TreeSet.

HashSet: Desempenho com Tabela Hash

Baseado no HashMap, o HashSet oferece operações de adição, remoção e busca em tempo constante médio O(1). A verificação de unicidade depende dos contratos de hashCode() e equals().

import java.util.HashSet;
import java.util.Objects;

public class RegistroUsuarios {
    public static void main(String[] args) {
        HashSet<string> nomesUnicos = new HashSet<>();
        nomesUnicos.add("Ana");
        nomesUnicos.add("Bruno");
        nomesUnicos.add("Ana"); // Ignorado automaticamente

        System.out.println("Usuários registrados: " + nomesUnicos);
    }
}

// Classe de apoio para demonstrar hash/equals customizados
class Aluno {
    private String matricula;
    private int anoLetivo;

    public Aluno(String matricula, int anoLetivo) {
        this.matricula = matricula;
        this.anoLetivo = anoLetivo;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Aluno)) return false;
        Aluno outro = (Aluno) o;
        return anoLetivo == outro.anoLetivo && matricula.equals(outro.matricula);
    }

    @Override
    public int hashCode() {
        return Objects.hash(matricula, anoLetivo);
    }
}</string>

TreeSet: Ordenação Automática

Utiliza uma árvore rubro-negra internamente. Garante unicidade e mantém os elementos ordenados. Suporta ordenação natural (Comparable) ou personalizada (Comparator).

import java.util.Comparator;
import java.util.TreeSet;

public class CatalogoProdutos {
    public static void main(String[] args) {
        // Ordenação natural de strings
        TreeSet<string> frutas = new TreeSet<>();
        frutas.add("Maçã");
        frutas.add("Uva");
        frutas.add("Banana");
        System.out.println(frutas);

        // Ordenação customizada via Comparator: preço crescente, depois nome
        TreeSet<produto> estoque = new TreeSet<>((p1, p2) -> {
            int cmp = Integer.compare(p1.preco, p2.preco);
            return (cmp != 0) ? cmp : p1.nome.compareTo(p2.nome);
        });

        estoque.add(new Produto("Notebook", 3000));
        estoque.add(new Produto("Mouse", 50));
        estoque.add(new Produto("Teclado", 150));
        estoque.add(new Produto("Mouse", 50)); // Duplicata ignorada

        System.out.println("Estoque ordenado: " + estoque);
    }
}

class Produto {
    String nome;
    int preco;
    Produto(String n, int p) { nome = n; preco = p; }
    public String toString() { return nome + " (R$" + preco + ")"; }
}</produto></string>

Interface Map: Mapeamento Chave-Valor

A interface Map armazena pares chave-valor, onde cada chave deve ser única. Não é uma subinterface de Collection. Pricnipais implementações: HashMap, TreeMap, LinkedHashMap e Hashtable.

HashMap vs Hashtable

  • HashMap: Não sincronizado, permite chaves e valores null, maior desempenho.
  • Hashtable: Sincronizado, proíbe null, legado. Substitua por ConcurrentHashMap em cenários concorrentes.
import java.util.HashMap;
import java.util.Map;

public class ComparacaoMapas {
    public static void main(String[] args) {
        HashMap<string string=""> mapModerno = new HashMap<>();
        mapModerno.put(null, "valor_nulo");
        mapModerno.put("chave_valida", null);
        mapModerno.put(null, null);
        System.out.println("HashMap aceita nulos: " + mapModerno);

        // Hashtable lançaria NullPointerException nas operações acima
        // Hashtable<string string=""> tableLegado = new Hashtable<>();
    }
}</string></string>

Contagem de Frequência de Caracteres

Exemplo prático de uso de Map para analisar dados textuais:

import java.util.Map;
import java.util.TreeMap;

public class AnaliseFrequencia {
    public static void main(String[] args) {
        String textoEntrada = "aababcabcdabcde";
        Map<character integer=""> contador = new TreeMap<>();

        textoEntrada.chars().mapToObj(c -> (char) c)
                    .forEach(c -> contador.merge(c, 1, Integer::sum));

        StringBuilder resultado = new StringBuilder();
        contador.forEach((k, v) -> resultado.append(k).append("(").append(v).append(")"));
        System.out.println(resultado.toString());
    }
}</character>

LinkedHashMap: Preservação de Ordem de Inserção

Combina a performance de hash com uma lista encadeada que registra a ordem de adição. Útil para caches LRU ou quando a sequência importa.

import java.util.LinkedHashMap;
import java.util.Map;

public class ConfiguracoesSistema {
    public static void main(String[] args) {
        LinkedHashMap<string string=""> props = new LinkedHashMap<>();
        props.put("DB_HOST", "localhost");
        props.put("DB_PORT", "5432");
        props.put("CACHE_TTL", "3600");
        props.put("LOG_LEVEL", "DEBUG");

        props.forEach((k, v) -> System.out.println(k + " = " + v));
    }
}</string>

Utilitário Collections

A classe Collections fornece métodos estáticos para manipulação segura e eficiente de coleções. Um uso comum é a proteção de coleções padrão para ambientes multithread:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ColecaoThreadSafe {
    public static void main(String[] args) {
        List<string> listaBase = new ArrayList<>();
        listaBase.add("ItemA");
        listaBase.add("ItemB");

        // Envolve a lista não segura em uma wrapper sincronizada
        List<string> listaProtegida = Collections.synchronizedList(listaBase);
        
        System.out.println("Lista segura: " + listaProtegida);
    }
}</string></string>

Tags: java Collections ArrayList HashMap TreeSet

Publicado em 9-22 13:26