Programação Orientada a Objetos

Java Collections Framework

Objetivos da aula

  • Compreender o papel do Java Collections Framework
  • Diferenciar interfaces, implementações e algoritmos
  • Conhecer List, Set, Queue, Deque e Map
  • Realizar operações comuns em coleções
  • Reconhecer diferenças de desempenho das coleções
Prof. Fabricio Santana
fabricio.santana@idp.edu.br
www.linkedin.com/in/fabriciofsantana/
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Por que coleções se já existe Array?

  • Array: estrutura de dados de tamanho fixo que armazena dados do mesmo tipo de maneira contínua
    • Limitações
      • pouca expressividade sobre intenção
      • operações comuns precisam ser implementadas manualmente
      • remoção, busca, ordenação e agrupamento viram código repetitivo
    • Quando usar?
      • tamanho é conhecido e fixo
      • precisa de acesso rápido por índice (performance)
    • Quando evitar?
      • necessidade de redimensionamento dinâmico
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Coleção: o que é?

Ideia central

Coleções são estruturas de dados para organizar e manipular grupos de objetos, permitindo, de forma padronizada, adicionar, remover , pesquisar e percorrer.

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Coleção: principais benefícios

  • Organização: mantém vários elementos juntos de forma estruturada
  • Eficiência: oferece operações prontas para manipular dados
  • Segurança: reduz erros e facilita o gerenciamento dos dados
  • Flexibilidade: existem diferentes tipos de coleções para diferentes necessidades
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: arquitetura

Arquitetura unificada

O Java Collections Framework é uma arquitetura formada que oferece estrutura de dados para organizar e manipular grupos de objetos independentemente dos detalhes de implementação.

Organização

O Java Collections Framework está organizado no pacote java.util por meio de uma série de classes e interfaces

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: estrutura de dados

Principais estruturas de dados

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: principais interfaces

As interfaces estão disponíveis no pacote java.util.

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: interfaces de coleção

As interfaces garantem a flexibilidade do collections framework

Interface Descrição
Collection Interface raiz da hierarquia de coleções. Dela derivam interfaces como Set, Queue e List.
SequencedCollection Coleção com ordem de encontro definida, acesso às extremidades e visão reversa.
Set Coleção que não permite elementos duplicados.
SequencedSet Conjunto com ordem de encontro previsível e operações nas extremidades.
SortedSet Coleção ordenada que não permite elementos duplicados.
NavigableSet Conjunto ordenado com operações de navegação para vizinhos, extremos e ordem inversa.
List Coleção ordenada por posição que pode conter elementos duplicados.
Queue Coleção normalmente usada como fila, em geral com política primeiro a entrar, primeiro a sair.
Deque Fila de duas pontas; pode funcionar como fila ou pilha.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: interfaces de mapa

Map faz parte do Collections Framework, mas não herda de Collection.

Interface Descrição
Map Estrutura que associa chaves a valores e não permite chaves duplicadas. Não deriva de Collection.
SequencedMap Mapa com ordem de encontro definida, acesso à primeira/última entrada e visão reversa.
SortedMap Um Map com ordenação natural pela chave ou por um comparador.
NavigableMap Mapa ordenado com operações de navegação pelas chaves e visões em ordem inversa.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: principais classes

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: principais classes

As classes do collections framework estão disponíveis no pacote java.util.

Implementação Interface principal Descrição
ArrayList List Lista baseada em array redimensionável. Boa para acesso por índice e percorrimento.
LinkedList List / Deque Lista encadeada. Pode ser usada como lista, fila ou pilha.
HashSet Set Conjunto baseado em tabela hash. Não garante ordem dos elementos.
LinkedHashSet SequencedSet Conjunto baseado em hash que preserva ordem de inserção.
TreeSet SortedSet Conjunto ordenado, normalmente pela ordem natural dos elementos ou por um comparador.
ArrayDeque Deque Fila de duas pontas baseada em array redimensionável. Útil para filas e pilhas.
PriorityQueue Queue Fila em que a cabeça é definida por prioridade, ordem natural ou comparador.
HashMap Map Mapa baseado em tabela hash. Associa chaves a valores e não garante ordem.
LinkedHashMap SequencedMap Mapa baseado em hash que preserva ordem de inserção ou de acesso.
TreeMap SortedMap Mapa ordenado pelas chaves, usando ordem natural ou um comparador.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Coleção: interfaces vs. classes

Separar contrato de implementação

Uma interface define o que uma coleção deve fazer; uma classe concreta define como isso será feito.

Exemplo:

List<String> nomes = new ArrayList<>();
Set<Integer> matriculas = new HashSet<>();
Map<String, Aluno> alunosPorCpf = new HashMap<>();

A interface comunica intenção. A classe implementa a estrutura concreta.

Map também faz parte do Collections Framework, mas não herda de Collection: ele representa associação chave-valor.

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: critérios de escolha

Considere os seguintes critérios:

  • Ordenação: precisa manter a ordem dos elementos?
  • Duplicidade: pode haver elementos duplicados?
  • Eficiência: necessidade de acesso rápido por índice?
  • Alteração: muitas inserções e remoções?
  • Modelo: modelo de fila (FIFO) ou pilha (LIFO)?
  • Estrutura: precisa associar chave-valor?
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Java Collections Framework: qual escolher?

Necessidade Interface Implementação Critério de escolha
Lista ordenada por posição List ArrayList boa escolha padrão; acesso por índice eficiente.
Lista com operações nas extremidades List / Deque LinkedList útil nas extremidades; no meio, só compensa quando já há um iterador posicionado.
Conjunto sem repetição Set HashSet não garante ordem; busca e inserção tendem a ser eficientes.
Conjunto sem repetição em ordem de inserção SequencedSet LinkedHashSet preserva a ordem em que os elementos foram adicionados.
Conjunto sem repetição ordenado SortedSet TreeSet mantém elementos ordenados por ordem natural ou comparador.
Fila ou pilha Deque ArrayDeque boa opção para FIFO, LIFO e operações nas duas pontas.
Associação chave-valor Map HashMap acesso por chave sem garantia de ordem.
Mapa ordenado por chave SortedMap TreeMap mantém chaves em ordem natural ou por comparador.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayList: hierarquia

  • array redimensionável
  • mantém a ordem de inserção
  • permite elementos duplicados
  • permite valor nulo (null)
  • suporta generics
    • verifica tipo na compilação
  • não é thread-safe
  • complexidade das operações
    • acesso por índice: O(1)
    • adição no final: O(1) amortizado
    • remoção no final: O(1)
    • inserção/remoção no meio: O(n)
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayList: hierarquia simplificada

import java.util.ArrayList;
import java.util.List;
//...
ArrayList alunos = new ArrayList();

List professores = new ArrayList();

Generics

import java.util.ArrayList;
import java.util.List;
//...
ArrayList<String> alunos = new ArrayList<>();

List<Professor> professores = new ArrayList<>();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayList: principais métodos

  • add(E e): adiciona um elemento ao final da lista.
  • get(int i): retorna o elemento armazenado em uma posição.
  • set(int i, E e): substitui o elemento de uma posição.
  • remove(int i): remove o elemento localizado em uma posição.
  • contains(Object o): verifica se a lista contém determinado elemento.
  • indexOf(Object o): retorna a posição da primeira ocorrência ou -1.
  • size(): retorna a quantidade de elementos na lista.
  • isEmpty(): indica se a lista está vazia.
  • clear(): remove todos os elementos da lista.
  • getFirst() / getLast(): acessa o primeiro ou o último elemento da lista.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayList: exemplo

import java.util.ArrayList;
//...
ArrayList alunos = new ArrayList<>();

alunos.add(new Aluno("Fabricio"));
alunos.add(new Aluno("João"));

System.out.println(alunos); //[Fabricio, João]

System.out.println(alunos.get(1)); //João

alunos.set(0, "Maria");
System.out.println(alunos); //[Maria, João]

System.out.println(alunos.size()); // 2

alunos.remove(1);
System.out.println(alunos); //[Maria]

System.out.println(alunos.size()); // 1

alunos.add("Paulo"); // elemento com tipo diferente
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayList: exemplo com generics

Recomendação

Sempre definir o tipo de uma coleção

import java.util.ArrayList;
//...
ArrayList<Aluno> alunos = new ArrayList<>();

alunos.add(new Aluno("Fabricio"));
alunos.add(new Aluno("João"));

alunos.add("Paulo"); // Erro na compilação

As demais coleções serão apresentadas apenas com generics

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayList: iteração

Formas comuns de percorrer uma ArrayList:

ArrayList<String> nomes =
    new ArrayList<>();

nomes.add("Ana");
nomes.add("Bruno");
nomes.add("Carla");

for (int i = 0; i < nomes.size(); i++) {
    System.out.println(nomes.get(i));
}

for (String nome : nomes) {
    System.out.println(nome);
}
nomes.forEach(System.out::println);

Iterator<String> it = nomes.iterator();

while (it.hasNext()) {
    String nome = it.next();

    if (nome.startsWith("B")) {
        it.remove();
    }
}
  • Use for com índice quando a posição importa.
  • Use for-each ou forEach para leitura simples.
  • Use Iterator para remover durante a iteração.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedList: hierarquia

  • Lista duplamente encadeada
  • Usada como lista, fila ou pilha
    • List, Queue e Deque
  • Mantém a ordem de inserção
  • Permite elementos duplicados
  • Permite valores null
  • Consome mais memória
    • cada elemento aponta para o próximo e para o anterior
  • Complexidade das operações
    • acesso por índice: O(n)
    • inserção/remoção nas extremidades: O(1)
    • busca até uma posição no meio: O(n)
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedList: hierarquia simplificada

import java.util.LinkedList;
import java.util.Queue;
import java.util.Deque;
import java.util.List;
//...

LinkedList<String> alunos = new LinkedList<>();

List<Professor> professores = new LinkedList<>();

Queue<Registro> registro = new LinkedList<>();

Deque<Professor> filaProfessores = new LinkedList<>();

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedList: principais métodos

  • add(E e): adiciona um elemento ao final da lista.
  • addFirst(E e): adiciona um elemento no início.
  • addLast(E e): adiciona um elemento no fim.
  • get(int i): retorna o elemento armazenado em uma posição.
  • getFirst() / getLast(): acessa o primeiro ou o último elemento.
  • remove(int i): remove o elemento localizado em uma posição.
  • removeFirst() / removeLast(): remove o primeiro ou o último elemento.
  • peek(): consulta o primeiro elemento sem removê-lo.
  • poll(): remove e retorna o primeiro elemento, ou null se estiver vazia.
  • push(E e) / pop(): usa a lista como pilha.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedList: exemplo

import java.util.LinkedList;
//...

LinkedList<String> nomes = new LinkedList<>();

nomes.add("Ana");
nomes.addLast("Bruno");
nomes.addFirst("Carla");

System.out.println(nomes); //[Carla, Ana, Bruno]

System.out.println(nomes.getFirst()); //Carla

nomes.removeLast();
System.out.println(nomes); //[Carla, Ana]

nomes.push("Diego");
System.out.println(nomes.pop()); //Diego
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedList: iteração

LinkedList<String> nomes =
    new LinkedList<>();

nomes.add("Ana");
nomes.add("Bruno");
nomes.add("Carla");

for (String nome : nomes) {
    System.out.println(nome);
}

nomes.forEach(System.out::println);
Iterator<String> it = nomes.iterator();

while (it.hasNext()) {
    if (it.next().startsWith("B")) {
        it.remove();
    }
}

Iterator<String> inverso =
    nomes.descendingIterator();
  • Percorre em ordem de inserção.
  • Use descendingIterator() para ordem inversa.
  • Use Iterator para remover durante a iteração.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayDeque: hierarquia

  • Fila de duas pontas baseada em array redimensionável
  • Implementa Deque
  • Pode ser usada como fila ou pilha
  • Não permite valores null
  • Não é thread-safe
  • Complexidade das operações
    • inserção/remoção nas extremidades: O(1) amortizado
    • busca por elemento: O(n)
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayDeque: hierarquia simplificada

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Deque;
//...

ArrayDeque<String> historico = new ArrayDeque<>();

Queue<String> atendimentos = new ArrayDeque<>();

Deque<String> pilha = new ArrayDeque<>();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayDeque: principais métodos

  • add(E e): adiciona um elemento ao final.
  • addFirst(E e): adiciona um elemento no início.
  • addLast(E e): adiciona um elemento no fim.
  • offer(E e): tenta adicionar um elemento ao final.
  • getFirst() / getLast(): acessa o primeiro ou o último elemento.
  • peek() / peekFirst() / peekLast(): consulta elementos sem remover.
  • remove() / removeFirst() / removeLast(): remove elementos.
  • poll() / pollFirst() / pollLast(): remove ou retorna null se vazia.
  • push(E e) / pop(): usa o deque como pilha.
  • size() / isEmpty() / clear(): consulta ou limpa a coleção.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayDeque: exemplo

import java.util.ArrayDeque;
//...

ArrayDeque<String> tarefas = new ArrayDeque<>();

tarefas.addLast("A");
tarefas.addLast("B");
tarefas.addFirst("Urgente");

System.out.println(tarefas); //[Urgente, A, B]

System.out.println(tarefas.removeFirst()); //Urgente

tarefas.push("Topo");
System.out.println(tarefas.pop()); //Topo

System.out.println(tarefas.peek()); //A
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.ArrayDeque: iteração

ArrayDeque<String> tarefas =
    new ArrayDeque<>();

tarefas.addLast("A");
tarefas.addLast("B");
tarefas.addFirst("Urgente");

for (String tarefa : tarefas) {
    System.out.println(tarefa);
}

tarefas.forEach(System.out::println);
Iterator<String> inverso =
    tarefas.descendingIterator();

while (inverso.hasNext()) {
    System.out.println(inverso.next());
}

while (!tarefas.isEmpty()) {
    System.out.println(tarefas.poll());
}
  • for-each percorre do início para o fim.
  • descendingIterator() percorre do fim para o início.
  • poll() consome a fila removendo elementos.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Ordenação: Comparable e Comparator

Algumas coleções precisam comparar elementos para decidir prioridade ou posição.

Comparable<T>

  • Define a ordem natural da própria classe.
  • Usa o método compareTo.
  • Exemplo: String, Integer, LocalDate.
class Aluno implements Comparable<Aluno> {
    private String nome;
    private double nota;

    public int compareTo(Aluno outro) {
        return Double.compare(this.nota, outro.nota);
    }
}

Comparator<T>

  • Define uma ordem externa à classe.
  • Permite múltiplas regras de ordenação.
  • Muito usado em PriorityQueue, TreeSet e TreeMap.
Comparator<Aluno> porNome =
    Comparator.comparing(Aluno::nome);

Comparator<Aluno> porNotaDesc =
    Comparator.comparing(Aluno::nota).reversed();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.PriorityQueue: hierarquia

  • Fila baseada em prioridade
  • Implementa Queue
  • Mantém a cabeça da fila conforme ordem natural ou Comparator
  • A cabeça da fila é o elemento de maior prioridade
    • na ordem natural, é o menor elemento
  • A iteração não garante percorrer em ordem de prioridade
  • Não permite valores null
  • Não é thread-safe
  • Complexidade das operações
    • inserção e remoção da cabeça: O(log n)
    • consulta da cabeça: O(1)
    • busca por elemento: O(n)
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.PriorityQueue: hierarquia simplificada

import java.util.PriorityQueue;
import java.util.Queue;
//...

PriorityQueue<Integer> prioridades =
    new PriorityQueue<>();

Queue<Integer> fila =
    new PriorityQueue<>();

PriorityQueue<Aluno> porNota =
    new PriorityQueue<>(comparador);
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.PriorityQueue: principais métodos

  • add(E e): insere um elemento na fila de prioridade.
  • offer(E e): insere um elemento na fila de prioridade.
  • peek(): consulta a cabeça da fila sem remover.
  • element(): consulta a cabeça; lança exceção se estiver vazia.
  • poll(): remove e retorna a cabeça, ou null se estiver vazia.
  • remove(): remove e retorna a cabeça; lança exceção se estiver vazia.
  • remove(Object o): remove uma ocorrência específica, se existir.
  • comparator(): retorna o comparador usado, ou null se usa ordem natural.
  • contains(Object o): verifica se a fila contém determinado elemento.
  • size() / isEmpty() / clear(): consulta ou limpa a coleção.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.PriorityQueue: exemplo

import java.util.PriorityQueue;
import java.util.Comparator;
//...

PriorityQueue<Integer> senhas =
    new PriorityQueue<>();

senhas.offer(30);
senhas.offer(10);
senhas.offer(20);

System.out.println(senhas.peek()); //10

System.out.println(senhas.poll()); //10
System.out.println(senhas.poll()); //20

PriorityQueue<String> nomes =
    new PriorityQueue<>(
        Comparator.reverseOrder()
    );
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.PriorityQueue: iteração

PriorityQueue<Integer> senhas =
    new PriorityQueue<>();

senhas.offer(30);
senhas.offer(10);
senhas.offer(20);

for (Integer senha : senhas) {
    System.out.println(senha);
}

for-each não garante ordem de prioridade.

while (!senhas.isEmpty()) {
    System.out.println(senhas.poll());
}

Saída pela prioridade:

10
20
30
  • Use peek() para consultar a próxima prioridade.
  • Use poll() para processar em ordem de prioridade.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

ArrayList, LinkedList, ArrayDeque e PriorityQueue

Classe Uso típico Ordem null Ponto forte Cuidado
ArrayList lista geral inserção/índice permite acesso por índice O(1) inserção/remoção no meio custa O(n)
LinkedList lista, fila ou pilha inserção permite operações nas extremidades O(1) acesso por índice custa O(n)
ArrayDeque fila ou pilha extremidades não permite fila/pilha eficiente sem classes legadas não oferece acesso por índice
PriorityQueue fila por prioridade prioridade não permite remove primeiro o elemento prioritário for-each não percorre em ordem de prioridade
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Igualdade e hash

Coleções baseadas em hash dependem de equals() e hashCode() para identificar elementos ou chaves.

Onde isso aparece

  • HashSet: decide se um elemento já existe.
  • LinkedHashSet: combina unicidade com ordem previsível.
  • HashMap: localiza valores pela chave.
  • LinkedHashMap: localiza chaves e preserva ordem.
class Aluno {
    private String matricula;
    private String nome;

    // construtor, getters, equals e hashCode
}

Set<Aluno> alunos = new HashSet<>();

alunos.add(new Aluno("001", "Ana"));
alunos.add(new Aluno("001", "Ana"));

System.out.println(alunos.size()); //1
  • Em classes comuns, implemente equals() e hashCode() de forma consistente.
  • Se a igualdade é pela matrícula, use esse atributo nos dois métodos.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashSet: hierarquia

  • Conjunto baseado em tabela hash
  • Implementa Set
  • Não permite elementos duplicados
  • Não garante ordem de iteração
  • Permite um valor null
  • Não é thread-safe
  • Complexidade das operações
    • add, remove, contains e size: O(1), em média
    • iteração depende do tamanho e da capacidade interna
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashSet: hierarquia simplificada

import java.util.HashSet;
import java.util.Set;
//...

HashSet<String> linguagens = new HashSet<>();

Set<String> matriculas = new HashSet<>();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashSet: principais métodos

  • add(E e): adiciona o elemento se ele ainda não existir.
  • remove(Object o): remove o elemento, se estiver presente.
  • contains(Object o): verifica se o elemento pertence ao conjunto.
  • iterator(): percorre os elementos, sem ordem garantida.
  • size(): retorna a quantidade de elementos.
  • isEmpty(): indica se o conjunto está vazio.
  • clear(): remove todos os elementos.
  • toArray(): converte o conjunto para um array.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashSet: exemplo

import java.util.HashSet;
//...

HashSet<String> linguagens = new HashSet<>();

linguagens.add("Java");
linguagens.add("Python");
linguagens.add("Java");

System.out.println(linguagens.size()); //2

System.out.println(
    linguagens.contains("Java")
); //true

linguagens.remove("Python");
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashSet: iteração

HashSet<String> linguagens =
    new HashSet<>();

linguagens.add("Java");
linguagens.add("Python");
linguagens.add("JavaScript");

for (String linguagem : linguagens) {
    System.out.println(linguagem);
}

linguagens.forEach(System.out::println);
Iterator<String> it =
    linguagens.iterator();

while (it.hasNext()) {
    String linguagem = it.next();

    if (linguagem.startsWith("J")) {
        it.remove();
    }
}
  • A ordem de iteração não é garantida.
  • Use Iterator para remover com segurança.
  • Não use HashSet quando a ordem importar.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashSet: hierarquia

  • Conjunto baseado em hash e lista encadeada
  • Implementa SequencedSet
  • Não permite elementos duplicados
  • Mantém ordem de inserção
  • Permite um valor null
  • Não é thread-safe
  • Complexidade das operações
    • add, remove e contains: O(1), em média
    • iteração segue a ordem de inserção
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashSet: hierarquia simplificada

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.SequencedSet;
//...

LinkedHashSet<String> nomes =
    new LinkedHashSet<>();

Set<String> conjunto = new LinkedHashSet<>();

SequencedSet<String> sequenciado =
    new LinkedHashSet<>();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashSet: principais métodos

  • add(E e): adiciona o elemento se ele ainda não existir.
  • addFirst(E e): adiciona ou move o elemento para o início.
  • addLast(E e): adiciona ou move o elemento para o fim.
  • getFirst() / getLast(): acessa o primeiro ou o último elemento.
  • removeFirst() / removeLast(): remove o primeiro ou o último elemento.
  • reversed(): retorna uma visão na ordem inversa.
  • contains(Object o): verifica se o elemento pertence ao conjunto.
  • size() / isEmpty() / clear(): consulta ou limpa o conjunto.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashSet: exemplo

import java.util.LinkedHashSet;
//...

LinkedHashSet<String> nomes =
    new LinkedHashSet<>();

nomes.add("Bruno");
nomes.add("Ana");
nomes.add("Carla");
nomes.add("Ana");

System.out.println(nomes);
//[Bruno, Ana, Carla]

nomes.addFirst("Diego");
System.out.println(nomes.getFirst()); //Diego
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashSet: iteração

LinkedHashSet<String> nomes =
    new LinkedHashSet<>();

nomes.add("Bruno");
nomes.add("Ana");
nomes.add("Carla");

for (String nome : nomes) {
    System.out.println(nome);
}

Percorre em ordem de inserção:

Bruno
Ana
Carla
for (String nome : nomes.reversed()) {
    System.out.println(nome);
}

Iterator<String> it = nomes.iterator();

while (it.hasNext()) {
    if (it.next().startsWith("A")) {
        it.remove();
    }
}
  • reversed() oferece visão inversa.
  • A ordem é previsível.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeSet: hierarquia

  • Conjunto ordenado baseado em árvore
  • Implementa NavigableSet
  • Não permite elementos duplicados
  • Ordena por ordem natural ou Comparator
  • Com ordem natural, não aceita null
  • Com Comparator, null só funciona se o comparador tratar esse caso
  • Não é thread-safe
  • Complexidade das operações
    • add, remove e contains: O(log n)
    • navegação por menor/maior elemento: O(log n)
  • A ordenação deve ser consistente com equals
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeSet: hierarquia simplificada

import java.util.TreeSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.NavigableSet;
//...

TreeSet<String> nomes = new TreeSet<>();

Set<String> conjunto = new TreeSet<>();

SortedSet<String> ordenado = new TreeSet<>();

NavigableSet<String> navegavel = new TreeSet<>();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeSet: principais métodos

  • add(E e): adiciona o elemento se ele ainda não existir.
  • remove(Object o): remove o elemento, se estiver presente.
  • contains(Object o): verifica se o elemento pertence ao conjunto.
  • first() / last(): acessa o menor ou o maior elemento.
  • lower(E e) / higher(E e): navega para vizinhos estritos.
  • floor(E e) / ceiling(E e): navega para vizinhos inclusivos.
  • pollFirst() / pollLast(): remove o menor ou o maior elemento.
  • descendingSet(): retorna uma visão em ordem decrescente.
  • comparator(): retorna o comparador, ou null se usa ordem natural.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeSet: exemplo

import java.util.TreeSet;
//...

TreeSet<String> nomes = new TreeSet<>();

nomes.add("Bruno");
nomes.add("Ana");
nomes.add("Carla");
nomes.add("Ana");

System.out.println(nomes);
//[Ana, Bruno, Carla]

System.out.println(nomes.first()); //Ana
System.out.println(nomes.higher("Ana")); //Bruno
System.out.println(nomes.pollLast()); //Carla
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeSet: iteração

TreeSet<String> nomes =
    new TreeSet<>();

nomes.add("Bruno");
nomes.add("Ana");
nomes.add("Carla");

for (String nome : nomes) {
    System.out.println(nome);
}

Percorre em ordem natural:

Ana
Bruno
Carla
for (String nome : nomes.descendingSet()) {
    System.out.println(nome);
}

SortedSet<String> trecho =
    nomes.subSet("Ana", "Carla");
  • A iteração segue a ordenação do conjunto.
  • descendingSet() percorre em ordem inversa.
  • subSet() permite iterar por intervalo.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

HashSet, LinkedHashSet e TreeSet

Classe Ordem Duplicados null Ponto forte Cuidado
HashSet não garante não permite permite um operações básicas O(1), em média não use quando a ordem importa
LinkedHashSet inserção não permite permite um preserva a ordem de inserção custo extra para manter encadeamento
TreeSet ordenada não permite não com ordem natural mantém elementos sempre ordenados operações básicas custam O(log n)
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashMap: hierarquia

Map faz parte do Java Collections Framework, mas não é uma subinterface de Collection.

  • Mapa baseado em tabela hash
  • Implementa Map
  • Associa chaves a valores
  • Não permite chaves duplicadas
  • Não garante ordem de iteração
  • Permite uma chave null e múltiplos valores null
  • Não é thread-safe
  • Complexidade das operações
    • get e put: O(1), em média
    • iteração depende do tamanho e da capacidade interna
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashMap: hierarquia simplificada

import java.util.HashMap;
import java.util.Map;
//...

HashMap<String, Aluno> porCpf =
    new HashMap<>();

Map<String, Aluno> alunos =
    new HashMap<>();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashMap: principais métodos

  • put(K k, V v): associa uma chave a um valor.
  • get(Object k): retorna o valor associado à chave.
  • getOrDefault(Object k, V padrao): retorna valor ou padrão.
  • remove(Object k): remove o par associado à chave.
  • containsKey(Object k): verifica se a chave existe.
  • containsValue(Object v): verifica se algum valor existe.
  • keySet(): retorna uma visão das chaves.
  • values(): retorna uma visão dos valores.
  • entrySet(): retorna uma visão dos pares chave-valor.
  • size() / isEmpty() / clear(): consulta ou limpa o mapa.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashMap: exemplo

import java.util.HashMap;
//...

HashMap<String, Aluno> alunos =
    new HashMap<>();

alunos.put("001", new Aluno("Ana"));
alunos.put("002", new Aluno("Bruno"));

System.out.println(alunos.get("001"));

alunos.put("001", new Aluno("Carla"));
System.out.println(alunos.size()); //2

for (var entrada : alunos.entrySet()) {
    System.out.println(entrada.getKey());
}
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.HashMap: iteração

HashMap<String, Aluno> alunos =
    new HashMap<>();

alunos.put("001", new Aluno("Ana"));
alunos.put("002", new Aluno("Bruno"));

for (String matricula : alunos.keySet()) {
    System.out.println(matricula);
}

for (Aluno aluno : alunos.values()) {
    System.out.println(aluno);
}
for (Map.Entry<String, Aluno> entrada
        : alunos.entrySet()) {
    System.out.println(
        entrada.getKey()
        + ": "
        + entrada.getValue()
    );
}
  • keySet() percorre chaves.
  • values() percorre valores.
  • entrySet() é melhor quando precisa de chave e valor.
  • HashMap não garante ordem.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashMap: hierarquia

  • Mapa baseado em hash e lista encadeada
  • Implementa SequencedMap
  • Mantém ordem de inserção por padrão
  • Pode ser criado com ordem de acesso
    • útil em estratégias do tipo LRU
  • Permite uma chave null e múltiplos valores null
  • Não é thread-safe
  • Complexidade das operações
    • get e put: O(1), em média
    • iteração segue a ordem definida
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashMap: hierarquia simplificada

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SequencedMap;
//...

LinkedHashMap<String, Aluno> alunos =
    new LinkedHashMap<>();

Map<String, Aluno> mapa =
    new LinkedHashMap<>();

SequencedMap<String, Aluno> sequenciado =
    new LinkedHashMap<>();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashMap: principais métodos

  • put(K k, V v): associa uma chave a um valor.
  • putFirst(K k, V v): posiciona a entrada no início.
  • putLast(K k, V v): posiciona a entrada no fim.
  • get(Object k): retorna o valor associado à chave.
  • firstEntry() / lastEntry(): acessa primeira ou última entrada.
  • pollFirstEntry() / pollLastEntry(): remove primeira ou última entrada.
  • reversed(): retorna uma visão na ordem inversa.
  • keySet() / values() / entrySet(): visões do mapa.
  • size() / isEmpty() / clear(): consulta ou limpa o mapa.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashMap: exemplo

import java.util.LinkedHashMap;
//...

LinkedHashMap<String, String> capitais =
    new LinkedHashMap<>();

capitais.put("DF", "Brasília");
capitais.put("BA", "Salvador");
capitais.put("SP", "São Paulo");

System.out.println(capitais.keySet());
//[DF, BA, SP]

capitais.putFirst("RJ", "Rio");
System.out.println(capitais.firstEntry());
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.LinkedHashMap: iteração

LinkedHashMap<String, String> capitais =
    new LinkedHashMap<>();

capitais.put("DF", "Brasília");
capitais.put("BA", "Salvador");
capitais.put("SP", "São Paulo");

for (var entrada : capitais.entrySet()) {
    System.out.println(entrada);
}

Percorre em ordem de inserção.

for (var entrada
        : capitais.reversed().entrySet()) {
    System.out.println(entrada);
}

for (String uf : capitais.keySet()) {
    System.out.println(uf);
}
  • entrySet() mantém a ordem previsível do mapa.
  • reversed() permite percorrer na ordem inversa.
  • A ordem pode ser de inserção ou de acesso, conforme o construtor.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeMap: hierarquia

  • Mapa ordenado por chave
  • Implementa NavigableMap
  • Baseado em árvore rubro-negra
  • Ordena por ordem natural ou Comparator
  • Não permite chaves duplicadas
  • Com ordem natural, não aceita chave null
  • Valores null são permitidos
  • Não é thread-safe
  • Complexidade das operações
    • containsKey, get, put e remove: O(log n)
  • A ordenação deve ser consistente com equals
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeMap: hierarquia simplificada

import java.util.TreeMap;
import java.util.Map;
import java.util.SortedMap;
//...

TreeMap<String, Aluno> alunos =
    new TreeMap<>();

Map<String, Aluno> mapa =
    new TreeMap<>();

SortedMap<String, Aluno> ordenado =
    new TreeMap<>();
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeMap: principais métodos

  • put(K k, V v): associa uma chave a um valor.
  • get(Object k): retorna o valor associado à chave.
  • remove(Object k): remove o par associado à chave.
  • containsKey(Object k): verifica se a chave existe.
  • firstKey() / lastKey(): acessa menor ou maior chave.
  • lowerKey(K k) / higherKey(K k): navega para chaves vizinhas.
  • floorKey(K k) / ceilingKey(K k): navega com inclusão.
  • firstEntry() / lastEntry(): acessa menor ou maior entrada.
  • descendingMap(): retorna uma visão em ordem decrescente.
  • keySet() / values() / entrySet(): visões do mapa.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeMap: exemplo

import java.util.TreeMap;
//...

TreeMap<String, Integer> notas =
    new TreeMap<>();

notas.put("Bruno", 8);
notas.put("Ana", 10);
notas.put("Carla", 9);

System.out.println(notas.keySet());
//[Ana, Bruno, Carla]

System.out.println(notas.firstKey()); //Ana
System.out.println(notas.higherKey("Ana")); //Bruno
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.TreeMap: iteração

TreeMap<String, Integer> notas =
    new TreeMap<>();

notas.put("Bruno", 8);
notas.put("Ana", 10);
notas.put("Carla", 9);

for (var entrada : notas.entrySet()) {
    System.out.println(entrada);
}

Percorre em ordem crescente das chaves.

for (var entrada
        : notas.descendingMap().entrySet()) {
    System.out.println(entrada);
}

for (String nome : notas.keySet()) {
    System.out.println(nome);
}
  • A iteração segue a ordenação das chaves.
  • descendingMap() percorre em ordem inversa.
  • Útil quando a ordem das chaves faz parte do problema.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

HashMap, LinkedHashMap e TreeMap

Classe Ordem Chaves null Ponto forte Cuidado
HashMap não garante únicas uma chave; vários valores get e put O(1), em média não use quando a ordem importa
LinkedHashMap inserção ou acesso únicas uma chave; vários valores preserva ordem previsível custo extra para manter encadeamento
TreeMap ordenada por chave únicas sem chave nula com ordem natural; valores nulos possíveis mantém chaves sempre ordenadas operações principais custam O(log n)
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.Collections

A classe Collections reúne métodos estáticos que operam sobre coleções ou retornam coleções especializadas.

Ideia central

Ela oferece algoritmos reutilizáveis, wrappers e fábricas utilitárias sem depender de uma implementação específica.

Exemplos de uso:

  • ordenar, embaralhar, inverter e buscar em listas;
  • encontrar mínimo e máximo;
  • contar frequência de elementos;
  • criar coleções vazias, imutáveis ou com cópias repetidas;
  • criar views sincronizadas, não modificáveis ou com checagem dinâmica de tipo.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.Collections: principais algoritmos

Método Uso Observação
sort(list) ordena uma lista usa ordem natural ou comparador.
binarySearch(list, key) busca em lista ordenada a lista precisa estar previamente ordenada.
reverse(list) inverte a ordem modifica a lista recebida.
shuffle(list) embaralha elementos útil para simulações e sorteios.
min(coll) / max(coll) menor ou maior elemento usa ordem natural ou comparador.
frequency(coll, obj) conta ocorrências usa equals() para comparação.
disjoint(c1, c2) verifica se não há interseção retorna true se não compartilham elementos.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.Collections: exemplo

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

List<Integer> notas = new ArrayList<>();

Collections.addAll(notas, 8, 10, 6, 10);

Collections.sort(notas);
System.out.println(notas); //[6, 8, 10, 10]

System.out.println(Collections.max(notas)); //10
System.out.println(Collections.frequency(notas, 10)); //2

Collections.reverse(notas);
System.out.println(notas); //[10, 10, 8, 6]
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

java.util.Collections: wrappers e fábricas

Método Uso Cuidado
unmodifiableList(list) cria uma visão não modificável alterações na lista original podem aparecer na visão.
synchronizedList(list) cria uma visão sincronizada iteração ainda exige cuidado externo.
checkedList(list, type) verifica tipo em tempo de execução útil ao interoperar com código legado.
emptyList() retorna lista vazia imutável não permite adicionar elementos.
singletonList(obj) lista imutável com um elemento boa para retornar resultado único.
nCopies(n, obj) lista imutável com cópias repetidas não cria cópias independentes do objeto.

Operações como add, remove, clear ou algoritmos que alteram a lista (sort, reverse, shuffle) podem lançar UnsupportedOperationException em coleções não modificáveis ou de tamanho fixo.

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Fail-fast: detecção de erro

Muitas implementações possuem iteradores fail-fast.

O que isso significa?

Se a coleção for modificada de forma indevida enquanto está sendo percorrida, o iterador tenta detectar o problema rapidamente.

Esse comportamento é uma ajuda para encontrar bugs, não um mecanismo de controle de fluxo.

Exemplo do erro comum:

for (String nome : nomes) {
    nomes.remove(nome); // risco de ConcurrentModificationException
}

Para remover durante o percurso, use um Iterator e chame remove() no próprio iterador.

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Concorrência

Coleções usadas por várias threads exigem cuidado.

Interfaces e classes específicas ajudam nesse cenário:

  • BlockingQueue
  • ConcurrentMap
  • ConcurrentNavigableMap
  • CopyOnWriteArrayList
  • ConcurrentHashMap
  • ConcurrentSkipListMap
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Boas práticas

  • Programe para interfaces: List, Set, Map.
  • Escolha implementação conforme uso esperado.
  • Use generics sempre que possível.
  • Não dependa de ordem quando a implementação não garante ordem.
  • Implemente equals() e hashCode() corretamente em objetos usados em Set ou como chave de Map.
  • Prefira APIs prontas antes de reinventar estruturas.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Estudo de caso 1: cadastro de alunos

Cenário: uma coordenação precisa registrar alunos na ordem em que foram cadastrados.

Coleção escolhida: List<Aluno> com ArrayList.

Implementação

  1. Crie uma classe Aluno com atributos nome e matricula.
  2. Implemente construtor e métodos de acesso.
  3. Declare a variável pela interface: List<Aluno> alunos.
  4. Instancie com new ArrayList<>().
  5. Cadastre alunos com add().
  6. Liste em ordem de cadastro com for-each.
  7. Conte o total com size().

Verifique: alunos com o mesmo nome são permitidos; a ordem de inserção é preservada.

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Estudo de caso 2: inscrições únicas

Cenário: uma atividade complementar não pode receber a mesma matrícula duas vezes.

Coleção escolhida: Set<String>, primeiro com HashSet, depois com LinkedHashSet.

Implementação

  1. Declare Set<String> matriculas.
  2. Instancie com new HashSet<>().
  3. Insira matrículas com add().
  4. Insira uma matrícula repetida e observe o retorno de add().
  5. Exiba o total com size().
  6. Troque para new LinkedHashSet<>() e compare a ordem de iteração.

Verifique: a duplicidade continua bloqueada; a diferença está na previsibilidade da ordem.

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Estudo de caso 3: índice por matrícula

Cenário: a secretaria precisa localizar rapidamente um aluno pela matrícula.

Coleção escolhida: Map<String, Aluno> com HashMap.

Implementação

  1. Crie uma classe Aluno com atributos nome e matricula.
  2. Implemente construtor e métodos de acesso.
  3. Declare Map<String, Aluno> alunosPorMatricula.
  4. Instancie com new HashMap<>().
  5. Cadastre usando put(matricula, aluno).
  6. Busque com get(matricula).
  7. Percorra pares com entrySet().
  8. Teste uma matrícula repetida e observe a substituição do valor.

Verifique: a chave é única; o acesso deixa de depender da posição do aluno.

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Conclusão

Mensagem principal

O Java Collections Framework permite escrever código mais claro, reutilizável e eficiente ao separar intenção, contrato e implementação.

Para escolher bem:

  • comece pela interface;
  • pense em duplicidade, ordem, busca e concorrência;
  • só então escolha a implementação.
Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Prática

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana

Challenge

Programação Orientada a ObjetosJava Collections FrameworkProf. Fabricio Santana