Set e HashSet
Set é uma coleção sem duplicatas. Esta lição cobre o uso de Set e princípios de desduplicação.
Características da Interface Set
| Característica | Descrição |
|---|---|
| Não ordenada | Sem ordem fixa (HashSet) |
| Sem duplicatas | Desduplicação automática |
| Sem índice | Não pode acessar por índice |
HashSet
HashSet é baseado em HashMap e é a implementação de Set mais comumente usada.
Criando HashSet
import java.util.HashSet;
import java.util.Set;
Set<String> set1 = new HashSet<>();
Set<String> set2 = new HashSet<>(100); // Capacidade especificada
Set<String> set3 = new HashSet<>(set1); // De outra coleção
Operações Básicas
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
// Adicionar elementos
set.add("Alice");
set.add("Bob");
set.add("Charlie");
set.add("Alice"); // Duplicata, não será adicionado
System.out.println("Set: " + set); // [Alice, Bob, Charlie] (não ordenado)
// Verificar
System.out.println("Tamanho: " + set.size()); // 3
System.out.println("Contém Alice: " + set.contains("Alice")); // true
System.out.println("Está vazio: " + set.isEmpty()); // false
// Remover
set.remove("Bob");
System.out.println("Após remover: " + set);
// Percorrer
for (String name : set) {
System.out.println(name);
}
}
}
Princípio de Desduplicação
HashSet usa hashCode e equals para determinar se elementos são duplicatas.
Fluxo de Desduplicação
1. Calcular hashCode do elemento
2. Se hashCode diferente → não é duplicata
3. Se hashCode igual → chamar equals
4. equals retorna true → duplicata
5. equals retorna false → não é duplicata (colisão de hash)
Exemplo: Desduplicação de Objeto Personalizado
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// Deve sobrescrever hashCode e equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return name + "(" + age + ")";
}
public static void main(String[] args) {
Set<Student> set = new HashSet<>();
set.add(new Student("Alice", 20));
set.add(new Student("Bob", 22));
set.add(new Student("Alice", 20)); // Duplicata, não será adicionado
System.out.println("Tamanho: " + set.size()); // 2
System.out.println("Set: " + set);
}
}
TreeSet
TreeSet é baseado em árvore rubro-negra e os elementos são automaticamente ordenados.
Características
| Característica | Descrição |
|---|---|
| Ordenada | Elementos ordenados por ordem natural ou personalizada |
| Sem duplicatas | Desduplicação automática |
| Sem índice | Não pode acessar por índice |
Exemplo: TreeSet
import java.util.Set;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
// Ordem natural
Set<Integer> numbers = new TreeSet<>();
numbers.add(3);
numbers.add(1);
numbers.add(4);
numbers.add(1); // Duplicata, não será adicionado
numbers.add(5);
System.out.println("Conjunto ordenado: " + numbers); // [1, 3, 4, 5]
// Ordem de string
Set<String> names = new TreeSet<>();
names.add("Charlie");
names.add("Alice");
names.add("Bob");
System.out.println("Nomes ordenados: " + names); // [Alice, Bob, Charlie]
}
}
Ordem Personalizada
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class CustomSortDemo {
public static void main(String[] args) {
// Ordenar por comprimento
Set<String> words = new TreeSet<>(Comparator.comparingInt(String::length));
words.add("Hello");
words.add("Hi");
words.add("Java");
words.add("Go");
System.out.println("Por comprimento: " + words); // [Go, Hi, Java, Hello]
}
}
LinkedHashSet
LinkedHashSet mantém a ordem de inserção.
Características
| Característica | Descrição |
|---|---|
| Ordenada | Na ordem de inserção |
| Sem duplicatas | Desduplicação automática |
Exemplo: LinkedHashSet
import java.util.LinkedHashSet;
import java.util.Set;
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
set.add("Charlie");
set.add("Alice");
set.add("Bob");
System.out.println("Conjunto ordenado: " + set); // [Charlie, Alice, Bob]
}
}
Operações de Conjunto
União
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3));
Set<Integer> set2 = new HashSet<>(Arrays.asList(3, 4, 5));
Set<Integer> union = new HashSet<>(set1);
union.addAll(set2);
System.out.println("União: " + union); // [1, 2, 3, 4, 5]
Interseção
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
System.out.println("Interseção: " + intersection); // [3]
Diferença
Set<Integer> diff = new HashSet<>(set1);
diff.removeAll(set2);
System.out.println("Diferença: " + diff); // [1, 2]
Comparação de Set
| Característica | HashSet | TreeSet | LinkedHashSet |
|---|---|---|---|
| Ordem | Não ordenada | Ordenada | Ordem de inserção |
| Implementação | HashMap | Árvore rubro-negra | Lista ligada + HashMap |
| Performance | O(1) | O(log n) | O(1) |
| null | 1 permitido | Não permitido | 1 permitido |
Guia de Seleção
| Necessidade | Escolha |
|---|---|
| Não se importa com ordem | HashSet |
| Precisa de ordenação | TreeSet |
| Manter ordem de inserção | LinkedHashSet |
Exemplo: Prática de Desduplicação
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class RemoveDuplicates {
// Método 1: Desduplicação com Set
public static <T> List<T> removeDuplicates1(List<T> list) {
return new ArrayList<>(new LinkedHashSet<>(list));
}
// Método 2: Desduplicação com Stream
public static <T> List<T> removeDuplicates2(List<T> list) {
return list.stream().distinct().collect(Collectors.toList());
}
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Bob");
list.add("Alice");
list.add("Charlie");
list.add("Bob");
System.out.println("Original: " + list);
System.out.println("Desduplicado: " + removeDuplicates1(list));
}
}
❓ Perguntas Frequentes
P: Como escolher entre Set e List? R: Use Set para desduplicação. Use List quando precisar de elementos ordenados e duplicados.
P: Qual é a regra de ordenação do TreeSet? R: O padrão é ordenação natural (Comparable). Você pode personalizar com Comparator.
P: Por que o HashSet é rápido? R: Baseado em HashMap, usa hashCode para busca direta com complexidade de tempo O(1).
📖 Resumo
- Set não tem duplicatas: HashSet não é ordenado, TreeSet é ordenado, LinkedHashSet mantém ordem de inserção
- Desduplicação depende dos métodos hashCode e equals
- Operações de conjunto: união (addAll), interseção (retainAll), diferença (removeAll)
📝 Exercícios
- Desduplicação: Remova duplicatas de uma List mantendo a ordem original
- Interseção: Encontre a interseção de dois Sets
- Ordenação: Use TreeSet para ordenar strings por comprimento
Próxima Lição
Na próxima lição, aprenderemos sobre Map e HashMap — coleções de pares chave-valor.



