0% acharam este documento útil (0 voto)
27 visualizações24 páginas

Resumo Collections Java

O documento aborda o Java Collections Framework, essencial para o concurso PROCERGS 2025, destacando suas interfaces, implementações e algoritmos. Ele enfatiza a importância do domínio das collections para resolver questões práticas e teóricas, além de preparar o candidato para tópicos avançados como Streams API. O texto também fornece dicas específicas para a banca FUNDATEC e exemplos de código relevantes.

Enviado por

rodrigo
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
27 visualizações24 páginas

Resumo Collections Java

O documento aborda o Java Collections Framework, essencial para o concurso PROCERGS 2025, destacando suas interfaces, implementações e algoritmos. Ele enfatiza a importância do domínio das collections para resolver questões práticas e teóricas, além de preparar o candidato para tópicos avançados como Streams API. O texto também fornece dicas específicas para a banca FUNDATEC e exemplos de código relevantes.

Enviado por

rodrigo
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 24

Collections em Java - Resumo para Concurso PROCERGS

2025
Autor: Manus AI
Data: Julho de 2025
Concurso: PROCERGS 2025 - Analista em Computação (Programação Java)
Banca: FUNDATEC

Sumário

1. Introdução ao Java Collections Framework

2. Hierarquia das Collections

3. Interface Collection

4. Interface List

5. Interface Set

6. Interface Queue

7. Interface Map

8. Principais Classes de Implementação

9. Comparação de Performance

10. Dicas Específicas para a Banca FUNDATEC

11. Preparação para Tópicos Subsequentes

12. Exemplos de Código Importantes

13. Pontos de Atenção e Lembretes

14. Referências

Introdução ao Java Collections Framework

O Java Collections Framework (JCF) é uma arquitetura unificada para representar e manipular coleções de objetos em Java.
Introduzido no Java 2 (JDK 1.2) e constantemente aprimorado nas versões subsequentes, o framework fornece um conjunto de
interfaces, implementações e algoritmos que permitem aos desenvolvedores trabalhar com grupos de objetos de forma
eficiente e padronizada.

O que são Collections?

Uma collection (coleção) é simplesmente um objeto que agrupa múltiplos elementos em uma única unidade. As collections são
usadas para armazenar, recuperar, manipular e comunicar dados agregados. Tipicamente, elas representam itens de dados que
formam um grupo natural, como uma mão de cartas (uma coleção de cartas), um diretório de e-mails (uma coleção de
endereços de e-mail) ou uma lista telefônica (um mapeamento de nomes para números de telefone).

Benefícios do Collections Framework

O Java Collections Framework oferece diversos benefícios fundamentais que todo candidato ao concurso da PROCERGS deve
compreender:

Redução do Esforço de Programação: O framework fornece estruturas de dados e algoritmos úteis, eliminando a necessidade
de escrever essas funcionalidades do zero. Isso permite que os desenvolvedores se concentrem nas partes importantes de seus
programas, em vez de se preocuparem com os detalhes de baixo nível do gerenciamento de coleções.

Aumento da Velocidade e Qualidade do Programa: O framework fornece implementações de alto desempenho de estruturas
de dados e algoritmos úteis. Como as várias implementações de cada interface são intercambiáveis, os programas podem ser
facilmente ajustados alterando as implementações de coleção. Como você está livre dos detalhes de escrever suas próprias
estruturas de dados, você tem mais tempo para dedicar à qualidade e desempenho do programa.

Permite Interoperabilidade entre APIs Não Relacionadas: As interfaces de coleção são a linguagem vernacular pela qual as
APIs passam coleções de um lado para o outro. Se minha API de administração de rede fornece uma coleção de nomes de nós e
sua API de toolkit GUI espera uma coleção de cabeçalhos de coluna, nossas APIs irão interoperar perfeitamente, mesmo que
tenham sido escritas independentemente.

Reduz o Esforço para Aprender e Usar Novas APIs: Muitas APIs naturalmente tomam coleções como entrada e as fornecem
como saída. No passado, cada uma dessas APIs tinha uma pequena sub-API dedicada à manipulação de suas coleções. Havia
pouca consistência entre essas sub-APIs ad hoc, então você tinha que aprender cada uma do zero, e era fácil cometer erros ao
usá-las. Com o advento das interfaces de coleção padrão, o problema desapareceu.

Reduz o Esforço para Projetar Novas APIs: Este é o outro lado da vantagem anterior. Os designers e implementadores não
precisam mais reinventar a roda toda vez que criam uma API que depende de coleções; em vez disso, eles podem usar interfaces
de coleção padrão.

Promove a Reutilização de Software: Novas estruturas de dados que estão em conformidade com as interfaces de coleção
padrão são, por natureza, reutilizáveis. O mesmo vale para novos algoritmos que operam em objetos que implementam essas
interfaces.

Componentes do Collections Framework

O Collections Framework consiste em três componentes principais que trabalham em conjunto:

Interfaces: Estes são tipos de dados abstratos que representam coleções. As interfaces permitem que as coleções sejam
manipuladas independentemente dos detalhes de sua representação. Em linguagens orientadas a objetos, as interfaces
geralmente formam uma hierarquia. As principais interfaces do framework incluem Collection, Set, List, Queue, Deque e Map.

Implementações: Estas são as implementações concretas das interfaces de coleção. Em essência, elas são estruturas de dados
reutilizáveis. O framework fornece várias implementações para cada interface, otimizadas para diferentes cenários de uso. Por
exemplo, ArrayList e LinkedList são duas implementações diferentes da interface List.

Algoritmos: Estes são os métodos que executam computações úteis, como busca e classificação, em objetos que implementam
interfaces de coleção. Os algoritmos são ditos polimórficos: ou seja, o mesmo método pode ser usado em muitas
implementações diferentes da interface de coleção apropriada. Em essência, os algoritmos são funcionalidade reutilizável.

Importância para o Concurso PROCERGS 2025

Para o concurso da PROCERGS 2025, organizado pela FUNDATEC, o domínio do Collections Framework é fundamental por várias
razões. Primeiro, as questões de programação Java frequentemente abordam o uso correto das diferentes implementações de
collections, suas características de performance e quando usar cada uma. Segundo, o conhecimento sólido de collections é pré-
requisito para compreender tópicos mais avançados como Streams API, que será estudado posteriormente.

A banca FUNDATEC tem histórico de questões que testam não apenas o conhecimento teórico, mas também a aplicação prática
das collections. É comum encontrar questões que apresentam código Java e perguntam sobre o comportamento esperado, a
escolha da collection mais adequada para um cenário específico, ou a identificação de erros em implementações.

Além disso, o Collections Framework serve como base para muitos padrões de programação funcional em Java 8+, incluindo o
uso de lambdas e method references com collections. Compreender profundamente as collections facilitará significativamente o
aprendizado dos próximos tópicos do seu cronograma de estudos.
Hierarquia das Collections

Compreender a hierarquia das collections é essencial para dominar o framework e responder corretamente às questões de
concurso. A hierarquia é organizada de forma lógica, com interfaces mais gerais no topo e implementações específicas nas folhas
da árvore.

Estrutura Geral da Hierarquia

A hierarquia do Collections Framework pode ser dividida em duas grandes famílias:

Família Collection: Representa grupos de objetos individuais. Esta família inclui as interfaces Collection, List, Set e Queue,
juntamente com suas sub-interfaces e implementações.

Família Map: Representa mapeamentos de chaves para valores. A interface Map não estende Collection, formando uma
hierarquia separada, mas é considerada parte do Collections Framework devido à sua funcionalidade relacionada.

Hierarquia da Interface Collection

Collection (interface)
├── List (interface)
│ ├── ArrayList (classe)
│ ├── LinkedList (classe)
│ ├── Vector (classe)
│ └── Stack (classe)
├── Set (interface)
│ ├── HashSet (classe)
│ ├── LinkedHashSet (classe)
│ └── SortedSet (interface)
│ └── NavigableSet (interface)
│ └── TreeSet (classe)
└── Queue (interface)
├── PriorityQueue (classe)
├── LinkedList (classe)
└── Deque (interface)
├── ArrayDeque (classe)
└── LinkedList (classe)

Hierarquia da Interface Map

Map (interface)
├── HashMap (classe)
├── LinkedHashMap (classe)
├── Hashtable (classe)
│ └── Properties (classe)
├── SortedMap (interface)
│ └── NavigableMap (interface)
│ └── TreeMap (classe)
└── WeakHashMap (classe)

Características das Principais Interfaces

Collection: É a interface raiz da hierarquia de collections. Define as operações básicas que todas as collections devem suportar,
como adicionar, remover, verificar se contém um elemento, obter o tamanho, etc. Importante notar que Map não estende
Collection.

List: Representa uma coleção ordenada (também conhecida como sequência) que pode conter elementos duplicados. Os
elementos podem ser acessados por índice, e a interface fornece métodos para manipulação baseada em posição.

Set: Representa uma coleção que não pode conter elementos duplicados. Modela a abstração matemática de conjunto. Algumas
implementações mantêm ordem de inserção, outras mantêm ordem natural dos elementos.

Queue: Representa uma coleção projetada para manter elementos antes do processamento. Além das operações básicas de
Collection, as filas fornecem operações adicionais de inserção, extração e inspeção.

Map: Representa um mapeamento de chaves para valores. Não pode conter chaves duplicadas, e cada chave pode mapear para
no máximo um valor. Substitui a classe Dictionary abstrata.
Pontos Importantes para Concursos

Herança vs Implementação: É crucial entender que algumas classes implementam múltiplas interfaces. Por exemplo,
LinkedList implementa tanto List quanto Queue e Deque. Isso significa que uma LinkedList pode ser usada como lista, fila ou
deque.

Interfaces Marcadoras: Algumas interfaces como RandomAccess são interfaces marcadoras (marker interfaces) que não
definem métodos, mas indicam propriedades especiais das implementações.

Compatibilidade com Versões Anteriores: O framework mantém compatibilidade com classes legadas como Vector e
Hashtable, que foram retrofitadas para implementar as novas interfaces.

Relacionamentos Especiais: Certas relações na hierarquia são frequentemente testadas em concursos: - ArrayList implementa
List e RandomAccess - LinkedList implementa List, Queue e Deque - HashSet é implementado internamente usando HashMap -
TreeSet implementa NavigableSet, que estende SortedSet

Implicações Práticas da Hierarquia

A hierarquia bem definida permite polimorfismo efetivo. Você pode declarar uma variável usando uma interface mais geral e
atribuir qualquer implementação compatível. Por exemplo:

Collection<String> col = new ArrayList<>(); // Válido


List<String> list = new LinkedList<>(); // Válido
Set<String> set = new HashSet<>(); // Válido

Esta flexibilidade é fundamental para escrever código maintível e é frequentemente explorada em questões de concurso que
testam o entendimento sobre polimorfismo e design de APIs.

A compreensão sólida desta hierarquia também é essencial para os tópicos subsequentes do seu estudo, especialmente quando
trabalhar com Streams API, onde você frequentemente converterá entre diferentes tipos de collections ou aplicará operações
que retornam tipos específicos de collections.

Interface Collection

A interface [Link] é a raiz da hierarquia de coleções em Java. Ela define o comportamento comum que todas
as coleções de elementos devem ter, exceto os Map s. É uma interface genérica, o que significa que ela pode ser parametrizada
para armazenar elementos de um tipo específico, garantindo segurança de tipo em tempo de compilação.

Métodos Principais da Interface Collection

Os métodos definidos em Collection são operações fundamentais para gerenciar grupos de objetos. Conhecer esses métodos
é crucial para entender como as coleções funcionam e para responder a questões que envolvem a manipulação básica de dados.
Método Descrição Retorno Exemplo de Uso Observações

Opcional; algumas
Adiciona um elemento coleções podem
e à coleção. Retorna não permitir
boolean add(E e) boolean [Link]("Java");
true se a coleção foi elementos
modificada. duplicados ou
nulos.

Adiciona todos os
boolean elementos da coleção c
addAll(Collection<? à coleção atual. Retorna boolean [Link](anotherList);
extends E> c) true se a coleção foi

modificada.

Remove todos os
void clear() void [Link]();
elementos da coleção.

Retorna true se a Usa o método


boolean contains(Object
coleção contém o boolean [Link]("Java"); equals() para
o)
elemento o . comparação.

Retorna true se a
boolean
coleção contém todos os
containsAll(Collection<?> boolean [Link](subList);
elementos da coleção
c)
c.

Retorna true se a
boolean isEmpty() coleção não contém boolean [Link]();

elementos.

Retorna um iterador
Iterator<String> it = Essencial para
Iterator<E> iterator() sobre os elementos Iterator<E>
[Link](); percorrer a coleção.
desta coleção.

Remove uma única


instância do elemento
Usa o método
o da coleção, se
boolean remove(Object o) boolean [Link]("Java"); equals() para
presente. Retorna true
comparação.
se a coleção foi
modificada.

Remove todos os
elementos da coleção
boolean
atual que também estão
removeAll(Collection<?> boolean [Link](elementsToRemove);
presentes na coleção c .
c)
Retorna true se a
coleção foi modificada.

Retém apenas os
elementos na coleção
boolean
atual que também estão Operação de
retainAll(Collection<?> boolean [Link](elementsToKeep);
contidos na coleção c . interseção.
c)
Retorna true se a
coleção foi modificada.

Retorna o número de
int size() int [Link]();
elementos na coleção.

Retorna um array
contendo todos os
Object[] toArray() Object[] Object[] arr = [Link]();
elementos desta
coleção.
Método Descrição Retorno Exemplo de Uso Observações

Retorna um array
contendo todos os
elementos desta
String[] arr = [Link](new Mais seguro em
<T> T[] toArray(T[] a) coleção; o tipo de tempo T[]
String[0]); termos de tipo.
de execução do array
retornado é o do array
especificado.

Considerações Importantes para o Concurso

1. Contratos dos Métodos: A FUNDATEC pode explorar o conhecimento sobre o contrato dos métodos. Por exemplo, add()
pode lançar UnsupportedOperationException se a coleção não suporta a operação, ou NullPointerException se o
elemento é nulo e a coleção não permite nulos. remove() também pode lançar UnsupportedOperationException .

2. equals() e hashCode() : Os métodos contains() , remove() , containsAll() , removeAll() e retainAll() dependem


fortemente da implementação correta dos métodos equals() e hashCode() dos objetos armazenados na coleção. Se
esses métodos não forem sobrescritos corretamente para classes personalizadas, o comportamento da coleção pode ser
inesperado. Questões podem apresentar cenários onde a falta de implementação adequada desses métodos leva a
resultados incorretos.

3. Iteração: O método iterator() é fundamental para percorrer os elementos de uma coleção. O Iterator permite
remover elementos da coleção durante a iteração de forma segura, o que não é possível com um for-each loop
diretamente (lançaria ConcurrentModificationException se a coleção for modificada por outro meio durante a iteração).

4. Generics: A utilização de Generics ( <E> ) é um ponto chave. Garante segurança de tipo em tempo de compilação e evita
ClassCastException em tempo de execução. Questões podem apresentar código sem Generics para testar o
entendimento sobre os problemas que isso pode causar.

5. Operações de Conjunto: removeAll() e retainAll() são operações de conjunto (diferença e interseção,


respectivamente) que podem ser cobradas em cenários práticos.
Exemplo Básico de Uso da Interface Collection

import [Link];
import [Link];
import [Link];

public class ExemploCollection {


public static void main(String[] args) {
// Usando a interface Collection com uma implementação ArrayList
Collection<String> frutas = new ArrayList<>();

// Adicionando elementos
[Link]("Maçã");
[Link]("Banana");
[Link]("Laranja");
[Link]("Coleção após adicionar: " + frutas); // [Maçã, Banana, Laranja]

// Verificando o tamanho
[Link]("Tamanho da coleção: " + [Link]()); // 3

// Verificando se contém um elemento


[Link]("Contém 'Banana'? " + [Link]("Banana")); // true
[Link]("Contém 'Uva'? " + [Link]("Uva")); // false

// Removendo um elemento
[Link]("Banana");
[Link]("Coleção após remover 'Banana': " + frutas); // [Maçã, Laranja]

// Iterando sobre a coleção


[Link]("Elementos via Iterator:");
Iterator<String> it = [Link]();
while ([Link]()) {
String fruta = [Link]();
[Link]("- " + fruta);
if ([Link]("Maçã")) {
[Link](); // Remoção segura durante a iteração
}
}
[Link]("Coleção após iteração e remoção: " + frutas); // [Laranja]

// Verificando se está vazia


[Link]("Coleção está vazia? " + [Link]()); // false

// Limpando a coleção
[Link]();
[Link]("Coleção após limpar: " + frutas); // []
[Link]("Coleção está vazia? " + [Link]()); // true
}
}

Dominar a interface Collection é o primeiro passo para entender as interfaces mais específicas e suas implementações, que
serão detalhadas a seguir. A FUNDATEC pode apresentar questões que exigem a compreensão dos métodos básicos e suas
implicações, especialmente em relação à mutabilidade e à segurança de tipo.

Interface List

A interface [Link] estende Collection e representa uma coleção ordenada de elementos. Isso significa que os
elementos em uma List têm uma ordem específica (baseada na ordem de inserção ou em alguma outra lógica) e podem ser
acessados por seu índice (posição numérica). Além disso, uma List permite elementos duplicados.

Características Principais da List

Ordenada: Os elementos são armazenados e recuperados em uma sequência previsível. A ordem de inserção é geralmente
mantida.

Acesso por Índice: Os elementos podem ser acessados, inseridos ou removidos usando um índice inteiro (baseado em
zero), semelhante a um array.

Permite Duplicatas: Uma List pode conter múltiplas ocorrências do mesmo elemento.

Métodos Adicionais da Interface List

Além dos métodos herdados de Collection , a interface List adiciona métodos específicos para manipulação baseada em
índice e outras operações relacionadas à ordem:
Método Descrição Retorno Exemplo de Uso Observações

Insere o elemento Desloca elementos


void add(int index, E
especificado na posição void [Link](1, "C++"); subsequentes para
element)
index na lista. a direita.

Insere todos os
boolean addAll(int Desloca elementos
elementos da coleção
index, Collection<? boolean [Link](0, otherList); subsequentes para
c na lista, começando
extends E> c) a direita.
na posição index .

Retorna o elemento na
E get(int index) E String s = [Link](0);
posição index na lista.

Retorna o índice da
primeira ocorrência do Usa equals() para
int indexOf(Object o) int int idx = [Link]("Java");
elemento o na lista, ou comparação.
-1 se não encontrado.

Retorna o índice da
int lastIndexOf(Object última ocorrência do int idx = Usa equals() para
int
o) elemento o na lista, ou [Link]("Java"); comparação.
-1 se não encontrado.

Retorna um Permite iteração


ListIterator<E> ListIterator sobre os ListIterator<String> li = bidirecional e
ListIterator<E>
listIterator() elementos da lista (em [Link](); modificação da
ordem). lista.

Retorna um
ListIterator<E> ListIterator sobre os
ListIterator<String> li =
listIterator(int elementos da lista, ListIterator<E>
[Link]([Link]());
index) começando na posição
index .

Desloca elementos
Remove o elemento na
E remove(int index) E String removed = [Link](0); subsequentes para
posição index na lista.
a esquerda.

Substitui o elemento na
E set(int index, E posição index na lista String old = [Link](0, Retorna o elemento
E
element) pelo elemento "Python"); que foi substituído.
especificado.

Retorna uma visão da Alterações na sub-


List<E> subList(int
porção da lista entre List<String> sub = [Link](1, lista são refletidas
fromIndex, int List<E>
fromIndex (inclusive) e 3); na lista original e
toIndex)
toIndex (exclusive). vice-versa.

Principais Implementações da Interface List

As implementações mais comuns de List são ArrayList e LinkedList , cada uma com suas características de performance e
uso ideais.

ArrayList

Baseado em Array Redimensionável: Internamente, ArrayList usa um array para armazenar os elementos. Quando o
array interno fica cheio, um novo array maior é criado e os elementos são copiados.

Acesso Rápido por Índice ( get ): Operações de get(index) são muito rápidas (tempo constante, O(1)) porque o acesso a
elementos em um array é direto.
Inserção/Remoção Lenta no Meio: Inserir ou remover elementos no meio da lista é lento (tempo linear, O(n)) porque exige
o deslocamento de todos os elementos subsequentes.

Adição Rápida no Final: Adicionar elementos no final da lista é geralmente rápido (tempo constante amortizado, O(1)),
mas pode ser lento ocasionalmente se o array precisar ser redimensionado.

Melhor para: Cenários onde o acesso aleatório (por índice) é frequente e as inserções/remoções são mais comuns no final
da lista.

LinkedList

Baseado em Lista Duplamente Encadeada: Internamente, LinkedList armazena os elementos em nós, onde cada nó
contém o elemento e referências para o nó anterior e o próximo nó.

Acesso Lento por Índice ( get ): Acesso a elementos por índice é lento (tempo linear, O(n)) porque exige percorrer a lista do
início ou do fim até o índice desejado.

Inserção/Remoção Rápida em Qualquer Posição: Inserir ou remover elementos em qualquer posição é rápido (tempo
constante, O(1)) uma vez que o nó é encontrado. O tempo para encontrar o nó ainda é O(n).

Melhor para: Cenários onde inserções e remoções no início ou no meio da lista são frequentes, e o acesso por índice é
menos comum.

Implementa Deque : LinkedList também implementa a interface Deque (Double Ended Queue), o que a torna útil para
operações de fila e pilha (como addFirst , removeLast , etc.).

Vector e Stack (Legadas)

Vector : Similar a ArrayList , mas é sincronizado (thread-safe). Isso o torna mais lento em ambientes de thread única. É
uma classe legada e geralmente ArrayList é preferível, a menos que a sincronização explícita seja necessária (e mesmo
assim, [Link]() é geralmente uma opção melhor).

Stack : Estende Vector e implementa uma estrutura de dados LIFO (Last-In, First-Out). Possui métodos como push() ,
pop() , peek() . Também é legada e ArrayDeque é a implementação preferida para pilhas e filas.

Considerações para o Concurso FUNDATEC

1. Escolha da Implementação: Questões da FUNDATEC podem apresentar um cenário e pedir a List mais adequada.
Entender as diferenças de performance entre ArrayList e LinkedList é crucial. Por exemplo, para um log de eventos
onde novos eventos são sempre adicionados ao final e raramente acessados por índice, ArrayList seria uma boa escolha.
Para uma lista de tarefas onde tarefas são frequentemente adicionadas e removidas do início ou meio, LinkedList pode
ser mais eficiente.

2. ListIterator : Este iterador é mais poderoso que o Iterator básico, permitindo iteração bidirecional e modificação da
lista durante a iteração. Pode ser um ponto de detalhe em questões mais aprofundadas.

3. subList() : A natureza de 'visão' da subList é um ponto importante. Modificações na sub-lista afetam a lista original e
vice-versa. Isso pode ser fonte de pegadinhas em questões.

4. equals() e hashCode() em List : A interface List adiciona um contrato específico para equals() e hashCode() : duas
listas são consideradas iguais se contêm os mesmos elementos na mesma ordem. Isso é diferente de Set , onde a ordem
não importa.

5. Classes Legadas: Embora Vector e Stack sejam legadas, a FUNDATEC pode incluí-las em questões para testar o
conhecimento sobre suas características (sincronização, LIFO) e a preferência por alternativas modernas ( ArrayList ,
ArrayDeque ).
Exemplo de Uso da Interface List

import [Link];
import [Link];
import [Link];

public class ExemploList {


public static void main(String[] args) {
// Usando ArrayList
List<String> nomesArrayList = new ArrayList<>();
[Link]("Alice");
[Link]("Bob");
[Link]("Charlie");
[Link]("ArrayList: " + nomesArrayList); // [Alice, Bob, Charlie]

// Acessando por índice


[Link]("Elemento no índice 1 (ArrayList): " + [Link](1)); // Bob

// Inserindo no meio
[Link](1, "David");
[Link]("ArrayList após inserção: " + nomesArrayList); // [Alice, David, Bob, Charlie]

// Removendo por índice


String removido = [Link](2); // Remove Bob
[Link]("ArrayList após remoção: " + nomesArrayList + ", Removido: " + removido); // [Alice, David,
Charlie], Removido: Bob

// Usando LinkedList
List<String> nomesLinkedList = new LinkedList<>();
[Link]("Xavier");
[Link]("Yara");
[Link]("Zoe");
[Link]("LinkedList: " + nomesLinkedList); // [Xavier, Yara, Zoe]

// LinkedList como Deque (exemplo)


((LinkedList<String>) nomesLinkedList).addFirst("Walter");
[Link]("LinkedList após addFirst: " + nomesLinkedList); // [Walter, Xavier, Yara, Zoe]
}
}

O domínio da interface List e suas implementações é crucial, pois ela é uma das coleções mais utilizadas no desenvolvimento
Java. A FUNDATEC frequentemente testa a capacidade do candidato de escolher a implementação correta para um dado
problema e de entender as implicações de performance de cada escolha.

Interface Set

A interface [Link] estende Collection e representa uma coleção que não contém elementos duplicados. Ela modela
a abstração matemática de um conjunto. A principal característica de um Set é que cada elemento é único; se você tentar
adicionar um elemento que já existe no conjunto, a operação de adição não terá efeito e o método add() retornará false .

Características Principais da Set

Não Permite Duplicatas: Garante que todos os elementos armazenados no conjunto são únicos. A unicidade é
determinada pelo método equals() dos elementos.

Não Ordenada (Geralmente): A maioria das implementações de Set não garante uma ordem específica para os
elementos. A ordem de iteração pode não ser a ordem de inserção, nem uma ordem natural.

Acesso por Elemento: Não há acesso por índice, pois a ordem não é garantida.

Métodos da Interface Set

A interface Set não adiciona nenhum método novo além dos herdados de Collection . No entanto, o comportamento dos
métodos herdados é modificado para refletir a restrição de unicidade. Por exemplo, o método add(E e) retorna false se o
elemento já estiver presente no conjunto.

Principais Implementações da Interface Set

As implementações mais comuns de Set são HashSet , LinkedHashSet e TreeSet , cada uma com suas propriedades
específicas de performance e ordenação.
HashSet

Baseado em Tabela Hash: Internamente, HashSet utiliza um HashMap para armazenar seus elementos. Cada elemento
adicionado ao HashSet é armazenado como uma chave no HashMap , e um objeto Object dummy é usado como valor.

Não Garante Ordem: A ordem dos elementos em um HashSet não é garantida e pode mudar ao longo do tempo,
especialmente após adições ou remoções.

Performance: Oferece performance de tempo constante (O(1)) para operações básicas como add() , remove() ,
contains() e size() , assumindo que a função de hash distribui os elementos uniformemente. Esta é a implementação
de Set mais rápida para operações gerais.

Requer hashCode() e equals() : Para que HashSet funcione corretamente e garanta a unicidade dos elementos, a classe
dos objetos armazenados deve sobrescrever corretamente os métodos hashCode() e equals() . Se esses métodos não
forem implementados corretamente, HashSet pode falhar em identificar duplicatas.

LinkedHashSet

Mantém Ordem de Inserção: LinkedHashSet é uma subclasse de HashSet que mantém uma lista duplamente
encadeada de todos os seus elementos. Isso garante que a ordem de iteração seja a ordem em que os elementos foram
inseridos no conjunto.

Performance: A performance das operações básicas é ligeiramente inferior à de HashSet devido à sobrecarga de manter a
lista encadeada, mas ainda é geralmente O(1).

Uso: Útil quando a ordem de inserção é importante, mas a unicidade dos elementos também é necessária.

TreeSet

Baseado em Árvore Binária de Busca Balanceada (Red-Black Tree): Internamente, TreeSet utiliza um TreeMap para
armazenar seus elementos. Os elementos são armazenados em ordem natural (se implementarem Comparable ) ou de
acordo com um Comparator fornecido no momento da criação do TreeSet .

Elementos Ordenados: Os elementos são armazenados em ordem crescente (natural ou definida por Comparator ). Isso
significa que a iteração sobre um TreeSet sempre retornará os elementos em ordem ordenada.

Performance: As operações básicas como add() , remove() e contains() têm performance de tempo logarítmico (O(log
n)), o que é mais lento que HashSet mas mais rápido que List para grandes conjuntos de dados quando a ordem é
necessária.

Requer Comparable ou Comparator : Os elementos armazenados em um TreeSet devem ser comparáveis. Isso significa
que eles devem implementar a interface Comparable ou um Comparator deve ser fornecido ao TreeSet no momento da
sua criação. Se os elementos não forem comparáveis, uma ClassCastException será lançada.

Implementa SortedSet e NavigableSet : TreeSet implementa SortedSet (que adiciona métodos para obter o
primeiro/último elemento, subconjuntos, etc.) e NavigableSet (que adiciona métodos para navegação mais granular,
como lower() , floor() , ceiling() , higher() ).

Considerações para o Concurso FUNDATEC

1. Unicidade e equals() / hashCode() : A FUNDATEC pode apresentar questões que testam a compreensão da unicidade em
Set e a importância dos métodos equals() e hashCode() . Cenários onde esses métodos não são sobrescritos
corretamente para classes personalizadas são comuns em questões de pegadinha.

2. Escolha da Implementação: Saber quando usar HashSet (performance, sem ordem), LinkedHashSet (performance,
ordem de inserção) ou TreeSet (ordenado, performance logarítmica) é fundamental. Por exemplo, para remover
duplicatas de uma lista sem se preocupar com a ordem, HashSet é a melhor escolha. Para manter a ordem de inserção
enquanto garante unicidade, LinkedHashSet . Para ter elementos sempre ordenados, TreeSet .

3. Comparable e Comparator : A necessidade de Comparable ou Comparator para TreeSet é um ponto frequentemente


cobrado. Entender a diferença entre eles e como implementá-los é importante.
4. Operações de Conjunto: Set é ideal para operações matemáticas de conjunto como união ( addAll ), interseção
( retainAll ) e diferença ( removeAll ). Questões podem envolver a aplicação dessas operações.

Exemplo de Uso da Interface Set

import [Link];
import [Link];
import [Link];
import [Link];

public class ExemploSet {


public static void main(String[] args) {
// Usando HashSet (sem ordem garantida)
Set<String> hashSet = new HashSet<>();
[Link]("Maçã");
[Link]("Banana");
[Link]("Laranja");
[Link]("Maçã"); // Tentando adicionar duplicata
[Link]("HashSet: " + hashSet); // Ordem pode variar, Maçã aparece uma vez
[Link]("Adicionou Maçã novamente? " + [Link]("Maçã")); // false

// Usando LinkedHashSet (mantém ordem de inserção)


Set<String> linkedHashSet = new LinkedHashSet<>();
[Link]("Maçã");
[Link]("Banana");
[Link]("Laranja");
[Link]("Maçã");
[Link]("LinkedHashSet: " + linkedHashSet); // [Maçã, Banana, Laranja]

// Usando TreeSet (elementos ordenados naturalmente)


Set<String> treeSet = new TreeSet<>();
[Link]("Maçã");
[Link]("Banana");
[Link]("Laranja");
[Link]("Maçã");
[Link]("TreeSet: " + treeSet); // [Banana, Laranja, Maçã] (ordenado alfabeticamente)

// Exemplo de remoção
[Link]("Banana");
[Link]("HashSet após remover Banana: " + hashSet);

// Exemplo de contains
[Link]("HashSet contém Laranja? " + [Link]("Laranja")); // true
}
}

O conhecimento aprofundado da interface Set e suas implementações é vital para o concurso, especialmente no que diz
respeito à garantia de unicidade e às implicações de performance e ordenação de cada tipo de conjunto. A FUNDATEC pode
apresentar cenários onde a escolha da implementação correta de Set é crucial para a eficiência ou correção do código.

Interface Map

A interface [Link] é uma parte fundamental do Java Collections Framework, mas, diferentemente de List , Set e
Queue , ela não estende a interface Collection . Um Map representa um mapeamento de chaves para valores, onde cada
chave é única e mapeia para no máximo um valor. É ideal para armazenar pares de dados onde você precisa recuperar um valor
rapidamente usando uma chave específica.

Características Principais da Map

Pares Chave-Valor: Armazena dados como pares de chave e valor ( key-value pairs ).

Chaves Únicas: Cada chave em um Map deve ser única. Se você tentar adicionar um par com uma chave já existente, o
valor associado a essa chave será atualizado.

Valores Duplicados Permitidos: Diferentemente das chaves, os valores podem ser duplicados.

Não Ordenada (Geralmente): A maioria das implementações de Map não garante uma ordem específica para as chaves ou
valores.
Métodos Principais da Interface Map

Método Descrição Retorno Exemplo de Uso Observações

Associa o valor
especificado à chave
especificada neste mapa. Retorna null
V put(K key, V value) Se o mapa já continha um V (valor anterior) [Link]("Brasil", "Brasília"); se a chave não
mapeamento para a chave, existia.
o valor antigo é
substituído.

Retorna o valor ao qual a


chave especificada está
String capital =
V get(Object key) mapeada, ou null se este V
[Link]("Brasil");
mapa não contém
mapeamento para a chave.

Remove o mapeamento Retorna null


String removed =
V remove(Object key) para a chave especificada V (valor removido) se a chave não
[Link]("Brasil");
deste mapa, se presente. existia.

Retorna true se este


boolean
mapa contém um
containsKey(Object boolean [Link]("Brasil");
mapeamento para a chave
key)
especificada.

Retorna true se este


boolean
mapa mapeia uma ou mais
containsValue(Object boolean [Link]("Brasília");
chaves para o valor
value)
especificado.

Retorna o número de
int size() mapeamentos chave-valor int [Link]();
neste mapa.

Retorna true se este


boolean isEmpty() mapa não contém boolean [Link]();

mapeamentos chave-valor.

Copia todos os
void putAll(Map<?
mapeamentos do mapa
extends K, ? extends void [Link](otherMap);
especificado para este
V> m)
mapa.

Remove todos os
void clear() void [Link]();
mapeamentos deste mapa.

Retorna um Set de todas O Set


Set<String> chaves =
Set<K> keySet() as chaves contidas neste Set<K> retornado é uma
[Link]();
mapa. visão do mapa.

Retorna uma Collection A Collection


Collection<V> Collection<String> valores =
de todos os valores Collection<V> retornada é uma
values() [Link]();
contidos neste mapa. visão do mapa.

Retorna um Set de A melhor forma


Set<[Link]<K, V>> Set<[Link]<K, Set<[Link]<String, String>>
objetos [Link] de iterar sobre
entrySet() V>> entradas = [Link]();
contidos neste mapa. chaves e valores.
Principais Implementações da Interface Map

As implementações mais comuns de Map são HashMap , LinkedHashMap e TreeMap , cada uma com suas características de
performance e ordenação.

HashMap

Baseado em Tabela Hash: Internamente, HashMap utiliza uma tabela hash para armazenar os pares chave-valor. É a
implementação de Map mais utilizada e geralmente a mais rápida.

Não Garante Ordem: A ordem dos elementos em um HashMap não é garantida e pode mudar ao longo do tempo. Não há
garantia de que a ordem de iteração será a ordem de inserção ou qualquer outra ordem específica.

Performance: Oferece performance de tempo constante (O(1)) para operações básicas como put() , get() , remove() ,
containsKey() e size() , assumindo que a função de hash distribui as chaves uniformemente. Esta é a implementação
de Map mais rápida para operações gerais.

Requer hashCode() e equals() : Para que HashMap funcione corretamente e garanta a unicidade das chaves, a classe das
chaves deve sobrescrever corretamente os métodos hashCode() e equals() . Se esses métodos não forem
implementados corretamente, HashMap pode falhar em identificar chaves duplicadas ou em recuperar valores associados
a chaves existentes.

Permite uma chave null e múltiplos valores null : HashMap permite uma única chave null e múltiplos valores null .

LinkedHashMap

Mantém Ordem de Inserção: LinkedHashMap é uma subclasse de HashMap que mantém uma lista duplamente
encadeada de todos os seus elementos. Isso garante que a ordem de iteração seja a ordem em que os pares chave-valor
foram inseridos no mapa.

Performance: A performance das operações básicas é ligeiramente inferior à de HashMap devido à sobrecarga de manter a
lista encadeada, mas ainda é geralmente O(1).

Uso: Útil quando a ordem de inserção é importante, mas a performance de um HashMap é desejada.

TreeMap

Baseado em Árvore Binária de Busca Balanceada (Red-Black Tree): Internamente, TreeMap utiliza uma árvore binária
de busca balanceada para armazenar os pares chave-valor. As chaves são armazenadas em ordem natural (se
implementarem Comparable ) ou de acordo com um Comparator fornecido no momento da criação do TreeMap .

Chaves Ordenadas: As chaves são armazenadas em ordem crescente (natural ou definida por Comparator ). Isso significa
que a iteração sobre um TreeMap sempre retornará as chaves em ordem ordenada.

Performance: As operações básicas como put() , get() , remove() e containsKey() têm performance de tempo
logarítmico (O(log n)), o que é mais lento que HashMap mas mais rápido que List para grandes conjuntos de dados
quando a ordem das chaves é necessária.

Requer Comparable ou Comparator : As chaves armazenadas em um TreeMap devem ser comparáveis. Isso significa que
elas devem implementar a interface Comparable ou um Comparator deve ser fornecido ao TreeMap no momento da sua
criação. Se as chaves não forem comparáveis, uma ClassCastException será lançada.

Não permite chaves null : TreeMap não permite chaves null .

Implementa SortedMap e NavigableMap : TreeMap implementa SortedMap (que adiciona métodos para obter a
primeira/última chave, sub-mapas, etc.) e NavigableMap (que adiciona métodos para navegação mais granular, como
lowerKey() , floorKey() , ceilingKey() , higherKey() ).

Hashtable (Legada)

Sincronizada: Similar a HashMap , mas é sincronizada (thread-safe). Isso a torna mais lenta em ambientes de thread única.
É uma classe legada e geralmente ConcurrentHashMap ou [Link]() são preferíveis para uso em
ambientes multi-thread.
Não permite chaves ou valores null : Lança NullPointerException se tentar adicionar uma chave ou valor null .

Considerações para o Concurso FUNDATEC

1. Distinção Map vs Collection : A FUNDATEC pode tentar confundir o candidato sobre o fato de Map não estender
Collection . É importante reforçar que Map é uma estrutura de dados de pares chave-valor, enquanto Collection é para
grupos de elementos únicos.

2. Unicidade de Chaves e equals() / hashCode() : Assim como em HashSet , a correta implementação de equals() e
hashCode() para as classes usadas como chaves é vital para o funcionamento correto de HashMap e LinkedHashMap .
Questões podem explorar cenários onde essa regra é violada.

3. Escolha da Implementação: Saber quando usar HashMap (performance, sem ordem), LinkedHashMap (performance,
ordem de inserção) ou TreeMap (chaves ordenadas, performance logarítmica) é um ponto chave. Por exemplo, para um
cache simples, HashMap é ideal. Para um mapa onde a ordem de inserção é importante (ex: histórico de acesso),
LinkedHashMap . Para um dicionário onde as chaves precisam estar sempre ordenadas (ex: índice remissivo), TreeMap .

4. Iteração sobre Map : As três formas de iterar sobre um Map ( keySet() , values() , entrySet() ) são importantes.
entrySet() é geralmente a mais eficiente para iterar sobre chaves e valores simultaneamente.

5. null em HashMap vs TreeMap / Hashtable : A capacidade de HashMap de aceitar uma chave null e valores null é um
detalhe que pode ser cobrado, contrastando com TreeMap e Hashtable que não permitem chaves null .

Exemplo de Uso da Interface Map

import [Link];
import [Link];
import [Link];
import [Link];

public class ExemploMap {


public static void main(String[] args) {
// Usando HashMap (sem ordem garantida)
Map<String, String> capitaisHashMap = new HashMap<>();
[Link]("Brasil", "Brasília");
[Link]("Argentina", "Buenos Aires");
[Link]("Chile", "Santiago");
[Link]("HashMap: " + capitaisHashMap); // Ordem pode variar

// Acessando valor
[Link]("Capital do Brasil: " + [Link]("Brasil")); // Brasília

// Atualizando valor
[Link]("Brasil", "Nova Brasília");
[Link]("HashMap após atualização: " + capitaisHashMap); // {Brasil=Nova Brasília, ...}

// Usando LinkedHashMap (mantém ordem de inserção)


Map<String, String> capitaisLinkedHashMap = new LinkedHashMap<>();
[Link]("Brasil", "Brasília");
[Link]("Argentina", "Buenos Aires");
[Link]("Chile", "Santiago");
[Link]("LinkedHashMap: " + capitaisLinkedHashMap); // {Brasil=Brasília, Argentina=Buenos Aires,
Chile=Santiago}

// Usando TreeMap (chaves ordenadas naturalmente)


Map<String, String> capitaisTreeMap = new TreeMap<>();
[Link]("Brasil", "Brasília");
[Link]("Argentina", "Buenos Aires");
[Link]("Chile", "Santiago");
[Link]("TreeMap: " + capitaisTreeMap); // {Argentina=Buenos Aires, Brasil=Brasília, Chile=Santiago}

// Iterando sobre um Map usando entrySet()


[Link]("\nIterando sobre HashMap com entrySet():");
for ([Link]<String, String> entrada : [Link]()) {
[Link]("Chave: " + [Link]() + ", Valor: " + [Link]());
}
}
}

O domínio da interface Map e suas implementações é tão importante quanto o das interfaces Collection para o concurso. A
FUNDATEC frequentemente inclui questões que exigem a escolha da implementação de Map mais adequada para um problema
específico, considerando performance, ordenação e comportamento em relação a chaves e valores nulos.
Comparação de Performance

A escolha da implementação correta de uma interface de Collection ou Map é crucial para a performance de uma aplicação Java.
A FUNDATEC, em suas questões, pode apresentar cenários onde a eficiência é o fator determinante para a escolha da estrutura
de dados. Compreender as complexidades de tempo (Big O Notation) das operações mais comuns é fundamental.

Complexidade de Tempo das Operações Comuns

A tabela abaixo resume a complexidade de tempo das operações básicas para as implementações mais comuns. n representa o
número de elementos na coleção.

Operação ArrayList LinkedList HashSet LinkedHashSet TreeSet HashMap LinkedHashMap TreeMap

O(1) O(1) O(1)


add(element) O(1) O(1) amortizado O(log n) O(1) amortizado O(log n)
amortizado amortizado amortizado

add(index,
O(n) O(1) N/A N/A N/A N/A N/A N/A
element)

get(index) O(1) O(n) N/A N/A N/A N/A N/A N/A

O(1) O(1)
remove(element) O(n) O(n) O(1) amortizado O(log n) O(1) amortizado O(log n)
amortizado amortizado

remove(index) O(n) O(1) N/A N/A N/A N/A N/A N/A

O(1) O(1)
contains(element) O(n) O(n) O(1) amortizado O(log n) O(1) amortizado O(log n)
amortizado amortizado

size() O(1) O(1) O(1) O(1) O(1) O(1) O(1) O(1)

Iteração O(n) O(n) O(n) O(n) O(n) O(n) O(n) O(n)

Observações sobre a Tabela:

O(1) amortizado: Significa que a operação leva tempo constante na maioria das vezes, mas ocasionalmente pode levar
mais tempo (por exemplo, quando um ArrayList precisa ser redimensionado ou um HashMap precisa ser re-hashed).

O(n): Tempo linear, o tempo de execução cresce proporcionalmente ao número de elementos.

O(log n): Tempo logarítmico, o tempo de execução cresce muito lentamente com o número de elementos (típico de
estruturas baseadas em árvore).

N/A: Não aplicável, a operação não existe para essa interface/implementação.

Fatores que Afetam a Performance

Além da complexidade de tempo teórica, outros fatores práticos influenciam a performance:

1. Fator de Carga (Load Factor) e Capacidade Inicial de HashMap / HashSet :

O load factor (fator de carga) padrão é 0.75. Quando o número de elementos excede capacidade * load factor ,
a tabela hash é redimensionada (re-hashed), o que é uma operação cara (O(n)).

Definir uma initial capacity (capacidade inicial) adequada para HashMap e HashSet pode evitar re-hashing
frequente, melhorando a performance, especialmente ao adicionar muitos elementos de uma vez.

2. Implementação de hashCode() e equals() :

Uma má implementação de hashCode() (que gera muitos colisões) pode degradar a performance de HashSet e
HashMap de O(1) para O(n) no pior caso.

É crucial que equals() e hashCode() sejam consistentes: se dois objetos são equals() , seus hashCode() devem
ser iguais.
3. Uso de Comparable e Comparator em TreeSet / TreeMap :

A performance de TreeSet e TreeMap depende da eficiência da comparação dos elementos/chaves. Comparações


complexas podem impactar o tempo de execução.

4. Sincronização:

Classes legadas como Vector e Hashtable são sincronizadas, o que as torna thread-safe, mas introduz uma
sobrecarga de performance significativa em ambientes de thread única ou quando a sincronização não é necessária.

Para thread-safety, é geralmente preferível usar ConcurrentHashMap ou as versões sincronizadas fornecidas por
[Link]() , [Link]() , etc., que oferecem controle mais granular ou
são otimizadas para concorrência.

Dicas para o Concurso

Análise de Cenários: A FUNDATEC frequentemente apresenta um problema e pede a melhor estrutura de dados. Analise o
problema em termos de:

Necessidade de Ordem: Se a ordem de inserção ou uma ordem natural/definida é crucial.

Permissão de Duplicatas: Se elementos repetidos são permitidos ou não.

Frequência de Operações: Quais operações ( add , get , remove , contains ) serão mais frequentes e em que
posições (início, meio, fim).

Uso de Chaves/Valores: Se a estrutura é um mapeamento ou uma coleção simples.

ArrayList vs LinkedList :

Use ArrayList quando precisar de acesso rápido por índice ( get ) e a maioria das adições/remoções for no final da
lista.

Use LinkedList quando precisar de inserções/remoções rápidas no início ou meio da lista, e o acesso por índice for
menos frequente.

HashSet vs TreeSet vs LinkedHashSet :

Use HashSet para a performance mais rápida e quando a ordem não importa.

Use LinkedHashSet quando a ordem de inserção precisa ser mantida.

Use TreeSet quando os elementos precisam ser mantidos em ordem natural ou definida por um Comparator .

HashMap vs TreeMap vs LinkedHashMap :

Use HashMap para a performance mais rápida e quando a ordem das chaves não importa.

Use LinkedHashMap quando a ordem de inserção das chaves precisa ser mantida.

Use TreeMap quando as chaves precisam ser mantidas em ordem natural ou definida por um Comparator .

Dominar a comparação de performance e saber quando aplicar cada estrutura de dados é um diferencial importante para o
concurso da PROCERGS, pois demonstra não apenas conhecimento teórico, mas também a capacidade de tomar decisões de
design eficientes.

Dicas Específicas para a Banca FUNDATEC

A banca FUNDATEC é conhecida por elaborar questões que testam não apenas o conhecimento teórico, mas também a
capacidade do candidato de aplicar conceitos em cenários práticos e identificar detalhes importantes da linguagem Java. Para o
tópico de Collections, preste atenção aos seguintes pontos:

1. Compreensão Profunda das Interfaces vs. Implementações:


A FUNDATEC pode apresentar um trecho de código que declara uma variável com o tipo de uma interface ( List ,
Set , Map ) e a inicializa com uma implementação específica ( ArrayList , HashSet , HashMap ). Questões podem
perguntar sobre o comportamento do código, que dependerá da implementação concreta.

Exemplo: List<String> lista = new LinkedList<>(); e depois perguntar sobre a performance de


[Link](index) . A resposta deve considerar a performance de LinkedList para get() , que é O(n).

2. equals() e hashCode() :

Este é um ponto recorrente em questões de Collections, especialmente para HashSet e HashMap . A banca pode
apresentar uma classe personalizada sem a sobrescrita correta de equals() e hashCode() e perguntar o que
acontece ao adicionar objetos dessa classe a um Set ou usá-los como chaves em um Map .

Lembre-se do contrato: se dois objetos são equals() , seus hashCode() devem ser iguais. O inverso não é verdadeiro
(colisões de hash são permitidas, mas devem ser minimizadas).

3. Mutabilidade e ConcurrentModificationException :

Modificar uma coleção enquanto ela está sendo iterada (usando um for-each loop ou Iterator de forma incorreta)
pode levar a uma ConcurrentModificationException . A FUNDATEC pode incluir cenários onde essa exceção é
lançada.

A forma segura de remover elementos durante a iteração é usando o método remove() do Iterator .

4. Classes Legadas ( Vector , Hashtable , Stack ):

Embora não sejam as implementações mais recomendadas atualmente, a FUNDATEC pode incluir questões sobre elas
para testar o conhecimento sobre suas características (principalmente a sincronização e o fato de serem legadas) e a
preferência por alternativas modernas ( ArrayList , HashMap , ArrayDeque ).

5. Nulls em Collections e Maps:

Entenda quais implementações permitem ou não elementos/chaves/valores null . Por exemplo, HashMap permite
uma chave null e múltiplos valores null , enquanto TreeMap e Hashtable não permitem chaves null .

6. Operações de Conjunto ( Set ):

Questões podem envolver a aplicação de operações de conjunto como união ( addAll ), interseção ( retainAll ) e
diferença ( removeAll ) com Set s.

7. Sintaxe e Erros Comuns:

A banca pode apresentar trechos de código com pequenos erros de sintaxe ou lógica para que o candidato os
identifique. Preste atenção a detalhes como o uso de Generics, tipos de retorno de métodos e a forma correta de
chamar as operações.

8. Cenários de Uso:

A FUNDATEC gosta de apresentar problemas do mundo real e pedir a melhor estrutura de dados para resolvê-los. Por
exemplo, "Qual a melhor estrutura para armazenar registros de alunos onde cada aluno tem um ID único e você
precisa acessá-los rapidamente pelo ID?" (Resposta: HashMap<Integer, Aluno> ).

9. Imutabilidade ([Link]...):

Embora menos comum, a banca pode tocar no conceito de coleções imutáveis ou wrappers de coleções
( [Link]() , [Link]() , etc.) para testar a segurança e o design de
APIs.

Ao estudar, não se limite a memorizar definições. Tente entender o porquê de cada característica e quando usar cada tipo de
coleção. Pratique com questões de concursos anteriores da FUNDATEC para se familiarizar com o estilo da banca.
Preparação para Tópicos Subsequentes: Interfaces Funcionais, Lambdas, Method
Reference, Programação Funcional e Stream API

O Java Collections Framework é a base sobre a qual muitas das funcionalidades modernas do Java 8+ foram construídas,
especialmente no que diz respeito à Programação Funcional e à Stream API. Compreender bem as Collections é um pré-requisito
fundamental para dominar esses tópicos avançados, que são cada vez mais cobrados em concursos.

Interfaces Funcionais e Expressões Lambda com Collections

Interfaces Funcionais são interfaces com um único método abstrato (SAM - Single Abstract Method). Elas são o alvo das
Expressões Lambda e Method References. Muitas interfaces do Collections Framework, ou interfaces que interagem com
Collections, foram aprimoradas ou introduzidas no Java 8 para serem Interfaces Funcionais, permitindo o uso de Lambdas.

Comparator<T> : Uma das interfaces funcionais mais importantes para Collections. Usada para definir uma ordem de
classificação para elementos em TreeSet , TreeMap ou para classificar List s usando [Link]() ou
[Link]() . Antes do Java 8, exigia uma classe anônima; agora, pode ser implementada com uma Lambda: ```java //
Antes do Java 8 [Link](minhaLista, new Comparator() { @Override public int compare(String s1, String s2) { return
[Link](s2); } });

// Com Lambda (Java 8+) [Link]((s1, s2) -> [Link](s2)); // Ou ainda mais conciso com Method Reference
[Link](String::compareTo); ```

Predicate<T> : Usada para filtrar elementos. O método removeIf() (introduzido na interface Collection no Java 8)
aceita um Predicate para remover elementos que satisfazem uma condição: java List<Integer> numeros = new
ArrayList<>([Link](1, 2, 3, 4, 5, 6)); [Link](n -> n % 2 == 0); // Remove números pares
[Link](numeros); // [1, 3, 5]

Consumer<T> : Usada para realizar uma ação em cada elemento. O método forEach() (introduzido na interface
Iterable , que Collection estende) aceita um Consumer : java List<String> nomes = [Link]("Ana",
"Bruno", "Carlos"); [Link](nome -> [Link]("Olá, " + nome));

Stream API e Collections

A Stream API, introduzida no Java 8, fornece uma maneira poderosa e funcional de processar coleções de dados. Streams não
são estruturas de dados; eles são uma sequência de elementos que suportam operações sequenciais e paralelas. A ponte entre
Collections e Streams é feita principalmente pelo método stream() (e parallelStream() ) disponível na interface Collection .

Obtendo um Stream de uma Collection: java List<String> produtos = [Link]("TV", "Geladeira",


"Fogão", "Microondas"); Stream<String> streamProdutos = [Link]();

Operações Intermediárias (Lazy): Operações como filter() , map() , sorted() , distinct() retornam um novo
Stream e são executadas de forma lazy (somente quando uma operação terminal é invocada). Elas permitem transformar
e filtrar os dados da coleção sem modificar a coleção original. java List<Integer> idades = [Link](25, 30,
18, 45, 22, 30); [Link]() .filter(idade -> idade >= 25) // Filtra idades >= 25 .distinct() //
Remove duplicatas .sorted() // Ordena .forEach([Link]::println); // Imprime: 25, 30, 45

Operações Terminais (Eager): Operações como forEach() , collect() , reduce() , count() , min() , max() , sum() ,
average() produzem um resultado ou um efeito colateral e encerram o Stream. Após uma operação terminal, o Stream
não pode ser reutilizado. ```java List palavras = [Link]("Java", "Collections", "Stream", "Lambda"); long count =
[Link]() .filter(s -> [Link]() > 5) .count(); // Operação terminal [Link]("Palavras com mais de 5 letras:
" + count); // 2

// Coletando resultados de volta para uma Collection List palavrasGrandes = [Link]() .filter(s -> [Link]() > 5)
.collect([Link]()); [Link](palavrasGrandes); // [Collections, Lambda] ```
Programação Funcional e Imutabilidade

A Stream API promove um estilo de programação mais funcional, onde a imutabilidade é valorizada. As operações de Stream
não modificam a coleção original; elas produzem novos resultados. Isso contrasta com as operações tradicionais de Collections
que frequentemente modificam a coleção in-place.

Conexão com o Concurso

Para o concurso da PROCERGS, a FUNDATEC pode apresentar questões que combinam o conhecimento de Collections com as
novas funcionalidades do Java 8+:

Refatoração de Código: Um trecho de código tradicional usando loops para processar uma coleção pode ser apresentado,
e a questão pode pedir a versão refatorada usando Streams e Lambdas.

Análise de Saída: Dado um código que usa Streams e Lambdas em Collections, o candidato deve prever a saída.

Escolha da Melhor Abordagem: Cenários onde o uso de Streams pode simplificar o código ou melhorar a performance
(especialmente com parallelStream() ).

Conhecimento de Collectors : A classe [Link] é fundamental para transformar Streams de


volta em Collections ou para agrupar/sumarizar dados. Métodos como toList() , toSet() , toMap() , groupingBy() são
frequentemente cobrados.

Ao estudar Collections, tenha em mente como cada tipo de coleção se comporta quando convertida para um Stream e como as
operações de Stream podem ser aplicadas para manipular os dados de forma eficiente e concisa. Isso não só reforçará seu
conhecimento em Collections, mas também construirá uma base sólida para os próximos tópicos do seu estudo. A FUNDATEC
valoriza candidatos que demonstram conhecimento das práticas modernas de desenvolvimento Java.

Exemplos de Código Importantes

Para solidificar o entendimento e preparar-se para questões práticas, é fundamental revisar exemplos de código que
demonstrem o uso correto e as nuances das Collections. Estes exemplos cobrem cenários comuns e pontos que a FUNDATEC
pode explorar.

1. Removendo Duplicatas de uma Lista

Uma forma eficiente de remover duplicatas de uma List é convertê-la para um Set e depois de volta para uma List .
HashSet é a escolha mais comum para isso devido à sua performance.

import [Link];
import [Link];
import [Link];
import [Link];

public class RemoverDuplicatas {


public static void main(String[] args) {
List<String> comDuplicatas = new ArrayList<>();
[Link]("Java");
[Link]("Python");
[Link]("Java");
[Link]("C++");
[Link]("Python");

[Link]("Lista com duplicatas: " + comDuplicatas);

// Usando HashSet para remover duplicatas


Set<String> semDuplicatasSet = new HashSet<>(comDuplicatas);
List<String> semDuplicatasList = new ArrayList<>(semDuplicatasSet);

[Link]("Lista sem duplicatas (HashSet): " + semDuplicatasList);

// Se a ordem de inserção for importante, use LinkedHashSet


Set<String> semDuplicatasLinkedHashSet = new LinkedHashSet<>(comDuplicatas);
List<String> semDuplicatasLinkedList = new ArrayList<>(semDuplicatasLinkedHashSet);
[Link]("Lista sem duplicatas (LinkedHashSet, ordem preservada): " + semDuplicatasLinkedList);
}
}
2. Contando Frequência de Palavras com Map

HashMap é excelente para contar a frequência de ocorrências de elementos, como palavras em um texto.

import [Link];
import [Link];

public class ContarFrequenciaPalavras {


public static void main(String[] args) {
String texto = "Java é uma linguagem de programação. Java é muito usada.";
String[] palavras = [Link]().replaceAll("[.,]", "").split("\\s+");

Map<String, Integer> frequencia = new HashMap<>();

for (String palavra : palavras) {


[Link](palavra, [Link](palavra, 0) + 1);
}

[Link]("Frequência de palavras: " + frequencia);


// Saída esperada (ordem pode variar): {linguagem=1, de=1, muito=1, programação=1, é=2, java=2, uma=1, usada=1}
}
}

3. Ordenando uma Lista de Objetos Personalizados

Para ordenar objetos personalizados, você pode usar Comparable (para ordem natural) ou Comparator (para ordem
personalizada).

Usando Comparable

import [Link];
import [Link];
import [Link];

class Pessoa implements Comparable<Pessoa> {


String nome;
int idade;

public Pessoa(String nome, int idade) {


[Link] = nome;
[Link] = idade;
}

@Override
public String toString() {
return nome + " (" + idade + ")";
}

// Define a ordem natural: por idade, depois por nome


@Override
public int compareTo(Pessoa outra) {
int resultadoIdade = [Link]([Link], [Link]);
if (resultadoIdade != 0) {
return resultadoIdade;
} else {
return [Link]([Link]);
}
}
}

public class OrdenarPessoasComparable {


public static void main(String[] args) {
List<Pessoa> pessoas = new ArrayList<>();
[Link](new Pessoa("Ana", 30));
[Link](new Pessoa("Carlos", 25));
[Link](new Pessoa("Beatriz", 30));
[Link](new Pessoa("Daniel", 20));

[Link]("Pessoas antes da ordenação: " + pessoas);

[Link](pessoas); // Usa o compareTo da classe Pessoa

[Link]("Pessoas após ordenação (Comparable): " + pessoas);


// Saída esperada: [Daniel (20), Carlos (25), Ana (30), Beatriz (30)]
}
}
Usando Comparator (com Lambda)

import [Link];
import [Link];
import [Link];

// Reutiliza a classe Pessoa do exemplo anterior, mas não precisa implementar Comparable
// class Pessoa { ... }

public class OrdenarPessoasComparator {


public static void main(String[] args) {
List<Pessoa> pessoas = new ArrayList<>();
[Link](new Pessoa("Ana", 30));
[Link](new Pessoa("Carlos", 25));
[Link](new Pessoa("Beatriz", 30));
[Link](new Pessoa("Daniel", 20));

[Link]("Pessoas antes da ordenação: " + pessoas);

// Ordena por nome usando um Comparator com lambda


[Link]([Link](p -> [Link]));
[Link]("Pessoas após ordenação por nome (Comparator): " + pessoas);
// Saída esperada: [Ana (30), Beatriz (30), Carlos (25), Daniel (20)]

// Ordena por idade decrescente usando um Comparator com lambda


[Link]([Link](Pessoa::getIdade).reversed());
[Link]("Pessoas após ordenação por idade decrescente (Comparator): " + pessoas);
// Saída esperada: [Ana (30), Beatriz (30), Carlos (25), Daniel (20)] (se getIdade for adicionado à classe
Pessoa)
}
}

4. Usando Stream API para Filtrar e Coletar

import [Link];
import [Link];
import [Link];

public class StreamFilterCollect {


public static void main(String[] args) {
List<String> linguagens = [Link]("Java", "Python", "C++", "JavaScript", "C#", "Ruby");

// Filtrar linguagens que começam com 'J' e coletar em uma nova lista
List<String> linguagensComJ = [Link]()
.filter(s -> [Link]("J"))
.collect([Link]());

[Link]("Linguagens que começam com 'J': " + linguagensComJ); // [Java, JavaScript]

// Mapear para o tamanho da string e coletar em um Set (remove duplicatas de tamanho)


Set<Integer> tamanhosUnicos = [Link]()
.map(String::length) // Method Reference
.collect([Link]());

[Link]("Tamanhos únicos das linguagens: " + tamanhosUnicos); // [4, 5, 6, 8, 10]


}
}

Estes exemplos ilustram o uso prático das Collections e sua integração com recursos modernos do Java. A prática com esses
tipos de código é essencial para o concurso.

Pontos de Atenção e Lembretes

Para o concurso da PROCERGS 2025, com foco na banca FUNDATEC e na vaga de Analista em Computação com ênfase em
Programação de Sistemas na Tecnologia JAVA, é fundamental ter em mente alguns pontos cruciais sobre Collections:

1. Imutabilidade vs. Mutabilidade: A maioria das Collections em Java são mutáveis, ou seja, seu conteúdo pode ser alterado
após a criação. Esteja ciente das implicações disso, especialmente ao passar coleções como argumentos para métodos ou
ao trabalhar com concorrência. Para coleções imutáveis, use [Link]() ,
[Link]() , etc., ou as coleções imutáveis introduzidas no Java 9 ( [Link]() , [Link]() ,
[Link]() ).

2. Thread-Safety: As implementações padrão de Collections ( ArrayList , HashMap , HashSet , LinkedList , TreeMap ,


TreeSet , PriorityQueue , ArrayDeque ) não são thread-safe. Se você estiver trabalhando em um ambiente multi-
threaded, precisará sincronizar o acesso à coleção externamente (usando [Link]() ,
[Link]() , etc.) ou usar as classes de concorrência do pacote [Link] (como
ConcurrentHashMap , CopyOnWriteArrayList , BlockingQueue ). A FUNDATEC pode apresentar cenários de concorrência
para testar esse conhecimento.

3. Fail-Fast Iterators: Os iteradores retornados pelas implementações de Collections do Java são geralmente fail-fast. Isso
significa que, se a coleção for modificada estruturalmente (adição ou remoção de elementos, exceto via método remove()
do próprio iterador) por qualquer thread que não seja o iterador, uma ConcurrentModificationException será lançada.
Isso é uma medida de segurança para detectar bugs rapidamente.

4. Autoboxing/Unboxing: Ao usar tipos primitivos (int, double, boolean, etc.) com Collections (que armazenam apenas
objetos), o Java realiza automaticamente o autoboxing (conversão de primitivo para seu wrapper correspondente, ex: int
para Integer ) e unboxing (conversão de wrapper para primitivo). Embora conveniente, isso pode ter um pequeno impacto
na performance e pode levar a NullPointerException se um wrapper null for unboxed.

5. hashCode() e equals() Novamente: Não subestime a importância desses métodos. Eles são a base para o
funcionamento correto de HashSet , HashMap , LinkedHashSet e LinkedHashMap . Uma implementação incorreta é uma
fonte comum de bugs e uma pegadinha frequente em concursos.

6. Escolha da Estrutura Certa: Sempre analise os requisitos do problema:

Precisa de ordem de inserção? ArrayList , LinkedList , LinkedHashSet , LinkedHashMap .

Precisa de acesso rápido por índice? ArrayList .

Precisa de inserção/remoção rápida no início/meio? LinkedList .

Não pode ter duplicatas? Set (e suas implementações).

Precisa de elementos ordenados naturalmente ou por critério? TreeSet , TreeMap .

Precisa de mapeamento chave-valor? Map (e suas implementações).

Precisa de fila (FIFO) ou pilha (LIFO)? Queue , Deque ( LinkedList , ArrayDeque ).

7. Java 8+ e Programação Funcional: Lembre-se que o Collections Framework é a porta de entrada para a Stream API.
Pratique a conversão de Collections para Streams e o uso de operações intermediárias e terminais. Entenda como Lambdas
e Method References simplificam o código ao trabalhar com Collections (ex: forEach , removeIf , sort ).

8. Jargão e Nomenclatura: Familiarize-se com os termos técnicos: Collection , List , Set , Map , Queue , Deque ,
Iterator , ListIterator , Comparable , Comparator , hashCode , equals , fail-fast , thread-safe , autoboxing ,
unboxing , Stream API , Lambda Expressions , Method References .

Ao manter esses pontos em mente, você estará mais preparado para as nuances e pegadinhas que a banca FUNDATEC pode
apresentar em suas questões sobre o Java Collections Framework.

Referências

[1] Oracle. The Java™ Tutorials - Collections Framework. Disponível em:


[Link]

[2] Baeldung. Guide to Java Collections. Disponível em: [Link]

[3] GeeksforGeeks. Java Collections Framework. Disponível em: [Link]

[4] [Link]. Questões de Programação - Java para Concurso. Disponível em: [Link]
de-concursos/disciplinas/tecnologia-da-informacao-programacao/java/questoes

[5] Tec Concursos. Questões FUNDATEC - Java. Disponível em:


[Link]

[6] FreeCodeCamp. How to Use the Java Collections Framework – A Guide for Developers. Disponível em:
[Link]
[7] Medium. Java Collections Framework: List, Set, and Map Explained. Disponível em:
[Link]

[8] Vogella. Using Java lists and maps (Collections) - Tutorial. Disponível em:
[Link]

[9] W3resource. Java Collection: Exercises, Practice, Solution. Disponível em: [Link]
exercises/collection/[Link]

Você também pode gostar