Atualizado: 24/08/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Interface Set e Classe HashSet em Java

A interface Set, que faz parte do conjunto de Coleções do Java, estende a interface Collection para definir um contrato para coleções que não permitem elementos duplicados. Ela não introduz novos métodos, mas adapta o comportamento dos métodos herdados para garantir a unicidade. Por exemplo, o método add() só insere um elemento se ele ainda não estiver presente na coleção, retornando true em caso de sucesso e false caso contrário.

A Classe HashSet: Implementação Baseada em Tabela de Hash

A classe genérica HashSet<E> é uma das implementações mais comuns e eficientes da interface Set. Ela utiliza uma tabela de hash como estrutura de dados interna para armazenar seus elementos.

Uma tabela de hash é uma estrutura que associa cada objeto a uma chave única, chamada de código hash. Esse código permite que o HashSet localize, insira ou remova elementos com alta performance (em tempo médio constante, O(1)), pois não necessita percorrer a coleção. A principal consequência dessa abordagem é que a HashSet não garante a ordem de iteração dos elementos.

Construtores da Classe HashSet

Para instanciar um HashSet, pode-se utilizar um dos seguintes construtores:

  • HashSet(): Cria um conjunto vazio com capacidade inicial e fator de carga padrão.
  • HashSet(Collection<? extends E> col): Cria um conjunto contendo todos os elementos da coleção col, eliminando quaisquer duplicatas presentes na coleção de origem.
  • HashSet(int capacity): Cria um conjunto vazio com a capacidade inicial especificada. A capacidade padrão é 16.
  • HashSet(int capacity, float loadFactor): Cria um conjunto com a capacidade inicial e o fator de carga (loadFactor) especificados. O fator de carga, um valor entre 0.0 e 1.0, determina o quão cheia a tabela pode ficar antes de sua capacidade ser automaticamente aumentada.

Exemplo de Utilização

O código a seguir demonstra as operações fundamentais de um HashSet, incluindo a adição de elementos, a tentativa de inserir duplicatas e o trabalho com objetos personalizados.

import java.util.HashSet;

public class Program {

    public static void main(String[] args) {

        // Criação de um HashSet para armazenar Strings
        HashSet<String> states = new HashSet<String>();

        // Adição de elementos ao conjunto
        states.add("Germany");
        states.add("France");
        states.add("Italy");

        // Tentativa de adicionar um elemento que já existe na coleção
        boolean isAdded = states.add("Germany");
        // O método retorna false, pois o elemento não foi adicionado
        System.out.println("'Germany' was added again: " + isAdded);

        // O tamanho permanece 3, pois duplicatas são ignoradas
        System.out.printf("Set contains %d elements\n", states.size());

        // Iteração sobre os elementos (a ordem não é garantida)
        System.out.println("Elements in the set:");
        for(String state : states) {
            System.out.println(state);
        }

        // Remoção de um elemento
        states.remove("Germany");
        System.out.println("Set after removing 'Germany': " + states);

        // Utilização de um HashSet com objetos personalizados
        HashSet<Person> people = new HashSet<Person>();
        people.add(new Person("Mike"));
        people.add(new Person("Tom"));
        people.add(new Person("Nick"));

        System.out.println("People in the set:");
        for(Person p : people) {
            System.out.println(p.getName());
        }
    }
}

class Person {
    private String name;

    public Person(String value) {
        this.name = value;
    }

    public String getName() {
        return this.name;
    }
}

Nota importante: Para que a detecção de duplicatas funcione corretamente com objetos personalizados (como a classe Person), é fundamental que a classe sobrescreva os métodos equals(Object o) e hashCode(). Sem isso, o HashSet não será capaz de identificar dois objetos Person com o mesmo nome como sendo duplicados.

Resumo

  • A interface Set define uma coleção que armazena elementos únicos.
  • A classe HashSet é uma implementação de Set que utiliza uma tabela de hash, oferecendo alta performance para as operações de adição, remoção e busca.
  • A principal característica do HashSet é a garantia de unicidade dos elementos, em detrimento da manutenção da ordem de inserção.
  • Use Set e HashSet quando seu principal requisito for garantir que não haja elementos repetidos em uma coleção e a ordem não for um fator importante.

📝 Exercícios

Tarefa 1 (Teoria)

Descrição: Considere o trecho de código abaixo. Após a execução de todas as linhas, qual será o tamanho final do conjunto (numeros.size()) e por quê?

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

public class TesteSet {
    public static void main(String[] args) {
        Set<Integer> numeros = new HashSet<>();

        numeros.add(10);
        numeros.add(20);
        numeros.add(30);
        numeros.add(10); // Adicionando um valor duplicado
        numeros.add(20); // Adicionando outro valor duplicado

        System.out.println("Tamanho do conjunto: " + numeros.size());
    }
}

Alternativas:

  • O tamanho será 5, pois cinco operações add() foram chamadas.
  • O código lançará uma exceção ao tentar adicionar um elemento duplicado.
  • O tamanho será 3, pois a interface Set não permite elementos duplicados.
  • O tamanho será 2, pois apenas os elementos duplicados são mantidos.
  • O código não irá compilar.
Resposta

A resposta correta é: O tamanho será 3, pois a interface Set não permite elementos duplicados.

Explicação: A principal característica de qualquer implementação da interface Set, incluindo o HashSet, é a garantia de que ela conterá apenas elementos únicos.

  • As três primeiras chamadas add() inserem os valores 10, 20 e 30 com sucesso.
  • Quando o código tenta executar numeros.add(10); novamente, o HashSet verifica que o valor 10 já existe na coleção e, portanto, a operação é ignorada (o método add() retornaria false).
  • O mesmo acontece com a tentativa de adicionar 20 novamente. Como resultado, o conjunto conterá apenas os elementos {10, 20, 30}, e seu tamanho final será 3.

  • Tarefa 2 (Prática)

    Descrição: Você recebeu uma List de nomes que pode conter duplicatas. Sua tarefa é criar um método que receba essa lista e retorne um HashSet contendo apenas os nomes únicos.

    Código inicial:

    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    public class Main {
        public static void main(String[] args) {
            List<String> nomesComDuplicatas = new ArrayList<>();
            nomesComDuplicatas.add("Ana");
            nomesComDuplicatas.add("Carlos");
            nomesComDuplicatas.add("Ana");
            nomesComDuplicatas.add("Beatriz");
            nomesComDuplicatas.add("Carlos");
    
            HashSet<String> nomesUnicos = obterNomesUnicos(nomesComDuplicatas);
    
            System.out.println("Nomes únicos: " + nomesUnicos);
            // A ordem pode variar, mas a saída deve conter Ana, Carlos, Beatriz.
        }
    
        public static HashSet<String> obterNomesUnicos(List<String> nomes) {
            // Crie um HashSet a partir da lista de nomes para remover as duplicatas.
            // Dica: um dos construtores de HashSet é perfeito para isso.
    
        }
    }
    Resposta

    Solução:

    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    public class Main {
    public static void main(String[] args) {
    List<String> nomesComDuplicatas = new ArrayList<>();
    nomesComDuplicatas.add("Ana");
    nomesComDuplicatas.add("Carlos");
    nomesComDuplicatas.add("Ana");
    nomesComDuplicatas.add("Beatriz");
    nomesComDuplicatas.add("Carlos");
    
            HashSet<String> nomesUnicos = obterNomesUnicos(nomesComDuplicatas);
    
            System.out.println("Nomes únicos: " + nomesUnicos);
        }
    
        public static HashSet<String> obterNomesUnicos(List<String> nomes) {
            // O construtor de HashSet que recebe uma coleção já faz o trabalho
            // de iterar sobre os elementos e adicionar apenas os únicos.
            return new HashSet<>(nomes);
        }
    
    }
    

    Explicação: Este é um dos casos de uso mais comuns e elegantes do HashSet. O construtor HashSet(Collection c) recebe qualquer tipo de coleção (como uma ArrayList) e, ao criar o novo HashSet, ele itera sobre todos os elementos da coleção de origem. Para cada elemento, ele tenta adicioná-lo ao novo conjunto. Como o Set não permite duplicatas, apenas a primeira ocorrência de cada nome ("Ana", "Carlos", "Beatriz") é mantida, resultando em um conjunto com elementos únicos.

    Política de Privacidade

    Copyright © www.programicio.com Todos os direitos reservados

    É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

    Contato: programicio@gmail.com